Jörg: Songs neu nummerieren (php)

Hallo,

ich möchte in einem Verzeichnis allen Songs neue Nummern im Dateinamen voranstellen.

Die Songs sind jetzt bereits nummeriert (3stellige Zahl, ggf. mit Buchstaben dahinter, dann Leerzeichen und dann der Rest).

Also müsste ich die Dateinamen als Liste einlesen, anschließend von Anfang bis ersten Leerzeochen gegen eine fortlaufende Zahl austauschen und den Dateinamen wieder abspeichern.

Wie stelle ich das am sinnvollsten an?

Jörg

  1. Hallo,

    ich möchte in einem Verzeichnis allen Songs neue Nummern im Dateinamen voranstellen.

    Die Songs sind jetzt bereits nummeriert (3stellige Zahl, ggf. mit Buchstaben dahinter, dann Leerzeichen und dann der Rest).

    Also müsste ich die Dateinamen als Liste einlesen, anschließend von Anfang bis ersten Leerzeochen gegen eine fortlaufende Zahl austauschen und den Dateinamen wieder abspeichern.

    Wie stelle ich das am sinnvollsten an?

    Soetwas erledigt man mit einem Dateimanager. Z.B. kann der Total Commander das. Und nein, der Windows-Explorer ist immernoch kein Dateimanager…

    Es könnte auch Leute geben, die das per Einzeiler auf der Kommandozeile erledigen.

    Gruß
    Kalk

    1. Hi,

      Soetwas erledigt man mit einem Dateimanager. Z.B. kann der Total Commander das.

      Dann erkläre mal, wie ich das machen muss im Total Commander, dass er jeden Dateinamen eines Verzeichnisses von Anfang bis ersten Leerzeichen gegen eine fortlaufende Zahl austauscht.

      Danke im Voraus.

      Jörg

      1. Hallo,

        Dann erkläre mal,

        Du musst erstmal genau bestimmen, was die Rahmenbedingungen sind. Hat Rolf ja auch schon gesagt.

        TC hat ein Mehrfach-Umbenenn-Tool, das sehr flexibel daherkommt. Angefangen von Zähler über Datum/Zeit und Ersetzungen bis hin zu Regex-Möglichkeiten.

        Das beste daran, ist auch die Vorschau!

        Gruß
        Kalk

  2. Tach!

    Also müsste ich die Dateinamen als Liste einlesen, anschließend von Anfang bis ersten Leerzeochen gegen eine fortlaufende Zahl austauschen und den Dateinamen wieder abspeichern.

    Wie stelle ich das am sinnvollsten an?

    Solange keine Bedingungen zutreffen, dass das sicher im Mehrbenutzerbetrieb stattfinden muss, einfach der Reihe nach.

    Dateinamen einlesen, glob() liefert ein Array. Ich würde dann das Array flippen, sodass die Dateinamen zu Keys werden. Dann durchlaufen und die Werte (die neuen Namen) zu den Keys (die alten Namen) entsprechend berechnen. Zum Schluss durchlaufen und die Dateien umbenennen.

    dedlfix.

  3. Hallo Jörg,

    Wie stelle ich das am sinnvollsten an?

    die Technik kommt, wie immer, als letztes.

    Fang damit an, indem Du sagst, nach welchen Regeln Du die Nummern vergeben willst. Damit stellst Du ja eine Reihenfolge her.

    Die existierenden Nummern erzeugen auch eine Form von Reihenfolge. Soll die erhalten bleiben und nur "ordentlich" formatiert werden? Wenn Du diese Dateien hier einliest

    1a Mama - Heintje.mp3
    1b Atemlos - Helene Fischer.wav
    002 Atemlos - Helene Fischer.wav
    03a Hänschen Klein - Kinderchor Hintertupfingen.mp3
    03b Alle meine Entchen - Kinderchor Hintertupfingen.mp3
    

    und nach "Name" sortierst, käme als Reihenfolge 002, 03a, 03b, 1a, 1b heraus.

    Welche Anforderungen hast Du an die Reihenfolge-Bildung?

    Mal angenommen, du möchtest sie in einer gefühlt natürlichen Reihenfolge haben, also ohne Beachtung führender Nullen. Dann käme 1a, 1b, 002, 03a, 03b heraus. Und nun beginnst Du umzubenennen. Hui, die böse Helene, die beschert Dir gleich mal eine Rename-Kollision. D.h. Du musst vor dem Rename prüfen, ob das Ziel schon existiert. Wenn ja, die Kollisionskandidaten erstmal beiseite lassen und den Rest renamen. Danach sollten die Kollisionskandidaten kein Problem mehr sein, weil durch die fortlaufende Nummerierung ja der Name nun frei sein sollte.

    Und was ist mit Unterverzeichnissen? Nummerierst Du nur ein Verzeichnis oder operiert das irgendwie rekursiv? Welche Dateitypen willst Du verarbeiten? Hat der Dateityp einen Einfluss auf die Reihenfolge?

    Wenn das geklärt ist, kannst Du mit glob, scandir oder readdir ein Verzeichnis lesen, die Dateinamen standardisieren und die Dateien umbenennen.

    Rolf

    --
    sumpsi - posui - obstruxi
    1. Hallo Rolf,

      Wenn Du diese Dateien hier einliest

      Genau mein Humor...😂

      1a Mama - Heintje.mp3
      1b Atemlos - Helene Fischer.wav
      002 Atemlos - Helene Fischer.wav
      03a Hänschen Klein - Kinderchor Hintertupfingen.mp3
      03b Alle meine Entchen - Kinderchor Hintertupfingen.mp3
      

      und nach "Name" sortierst, käme als Reihenfolge 002, 03a, 03b, 1a, 1b heraus.

      Meine Songs sind wie folgt nummeriert:

      001 Mama - Heintje.mp3
      001b Atemlos - Helene Fischer.wav
      001c Atemlos - Helene Fischer.wav
      002 Hänschen Klein - Kinderchor Hintertupfingen.mp3
      003 Alle meine Entchen - Kinderchor Hintertupfingen.mp3
      

      und genau dieser Reihenfolge soll auch eingehalten werden, daher diese seltsame Art der Nummerierung.

      Welche Anforderungen hast Du an die Reihenfolge-Bildung?

      001 - 400, nur Ziffern/Zahlen erlaubt.

      Mal angenommen, du möchtest sie in einer gefühlt natürlichen Reihenfolge haben, also ohne Beachtung führender Nullen. Dann käme 1a, 1b, 002, 03a, 03b heraus. Und nun beginnst Du umzubenennen. Hui, die böse Helene, die beschert Dir gleich mal eine Rename-Kollision. D.h. Du musst vor dem Rename prüfen, ob das Ziel schon existiert. Wenn ja, die Kollisionskandidaten erstmal beiseite lassen und den Rest renamen. Danach sollten die Kollisionskandidaten kein Problem mehr sein, weil durch die fortlaufende Nummerierung ja der Name nun frei sein sollte.

      Dann würde aber die Reihenfolge nicht beibehalten. Also lieber die dateinamen in ein Array? Dann hätte ich den numerischen Index, der mir die Reiohenfolge gewährleistet.

      Und was ist mit Unterverzeichnissen? Nummerierst Du nur ein Verzeichnis oder operiert das irgendwie rekursiv? Welche Dateitypen willst Du verarbeiten? Hat der Dateityp einen Einfluss auf die Reihenfolge?

      Nur ein Verzeichnis, ca 400 Songs, alles mp3.

      Jörg

      1. <?php
        $list[] = '1a Mama - Heintje.mp3';
        $list[] = '1b Atemlos - Helene Fischer.wav';
        $list[] = '002 Atemlos - Helene Fischer.wav';
        $list[] = '03a Hänschen Klein - Kinderchor Hintertupfingen.mp3';
        $list[] = '03b Alle meine Entchen - Kinderchor Hintertupfingen.mp3';
        
        # Hier die Liste nach Gutdünken sortieren ...
        sort( $list );
        
        $i=0; $keys=[];
        foreach ( $list as $s ) {
        	$arr = explode( ' ', $s, 2 );
        	$newList[$arr[0]] = $arr[1];
        	if ( in_array ( $arr[0], $keys ) ) {
        			trigger_error("Fatal: Doppelter Marker: " . $arr[0],  E_USER_ERROR );
        	}
        	$keys[] = $arr[0];
        }
        
        $i=0; $listStepwidth=10;
        foreach ( $keys as $k ) {
        	$n   = sprintf( '%05d %s', $i *  $listStepwidth, $newList[$k] );
        	echo 'PHP: rename( "' . $list[$i]  . "\",\t\"" . $n . '" );' . PHP_EOL;
        	# rename( $list[$i], $n );
        	$i++;
        }
        
        1. 001 - 400, nur Ziffern/Zahlen erlaubt.

          Das würde ich nicht wieder machen. Erzeuge die neuen Namen mit einem Inkrement (Lasse also einen numerischen Abstand zwischen Items) dann kannst Du einfacher neue Dateien dazwischenschieben oder umsortieren. - und bei Bedarf neu nummerieren.

          Längere Dateinamen kosten "nichts"…

          1. Hallo Raketenskriptfix,

            010 Mama
            020 Atemlos
            030 Der Hahn ist tot

            gute Idee, aber bekanntlich ist jedes Nummerierungsschema nach gewisser Zeit zum Überlaufen verdammt. Wenn er das Rename-Tool erstmal hat, ist's auch wurscht 😉

            Eigentlich müsste man diese Hantiererei ja in den MP3 Tags machen. Es gibt genug Player, die sich nicht am Dateinamen scheren, sondern die MP3 Tags verarbeiten.

            Rolf

            --
            sumpsi - posui - obstruxi
            1. Hallo,

              010 Mama
              020 Atemlos
              030 Der Hahn ist tot

              gute Idee, aber bekanntlich ist jedes Nummerierungsschema nach gewisser Zeit zum Überlaufen verdammt. Wenn er das Rename-Tool erstmal hat, ist's auch wurscht 😉

              ich frage mich, warum Jörg überhaupt numerieren will. Ich finde Titel und Interpret (oder andersrum) eigentlich ganz okay als Dateinamen. Eventuell noch mit einer Prosa-Information angereichert, z.B. dass es sich um einen Konzert-Livemitschnitt oder eine Extended-Version handelt.

              Eigentlich müsste man diese Hantiererei ja in den MP3 Tags machen. Es gibt genug Player, die sich nicht am Dateinamen scheren, sondern die MP3 Tags verarbeiten.

              Eigentlich finde ich diese Tags überflüssig. Wenn ich die Kerndaten (s.o.) im Dateinamen habe und auf mp3-Tags verzichte, dann habe ich im Dateimanager alle wichtigen Informationen sofort im Blick. Einen Standalone-Player habe und nutze ich nicht. YMMV.

              Live long and pros healthy,
               Martin

              --
              Fische, die bellen, beißen nicht.
              1. Hi Martin,

                ich frage mich, warum Jörg überhaupt numerieren will. Ich finde Titel und Interpret (oder andersrum) eigentlich ganz okay als Dateinamen. Eventuell noch mit einer Prosa-Information angereichert, z.B. dass es sich um einen Konzert-Livemitschnitt oder eine Extended-Version handelt.

                Weil manche Titel/Interpret-Kombis den Interpreten vorangestellt haben und ich nicht 5 x hinterienander denselben Interpreten hören möchte.

                Ich möchte die einmal festgelegte Reihenfolge beibehalten.

                Jörg

                1. Hallo Jörg,

                  hab ich mir gedacht - aber ist dafür nicht eigentlich die Playlist da? Mit einer Shuffle-Funktion, im Zweifelsfall?

                  Rolf

                  --
                  sumpsi - posui - obstruxi
                  1. Hi Rolf,

                    hab ich mir gedacht - aber ist dafür nicht eigentlich die Playlist da? Mit einer Shuffle-Funktion, im Zweifelsfall?

                    Ich will die Songs einem Kumpel auf nem Stick geben fürs Autoradio. Und ich habe zum einen keinen Schimmer, was das Radio daraus macht (daher möglichst einfache Vorgabe seitens des dateinamens) und zweitens kann man sich so auch mal einfacher über einen Song austauschen (analog einer chinesichen Speisekarte, auf der die gerichte nummeriert sind).

                    Jörg

      2. Hallo Jörg,

        Dann würde aber die Reihenfolge nicht beibehalten.

        Du würdest sie nicht in dieser Reihenfolge umbenennen, aber am Ende würden sie schon die richtige Reihenfolge haben.

        Da fällt mir ein: Die Frage wäre noch, ob Du sowas wie einen "directory sort" erreichen willst, der die Dateien im Ordner auch ohne expliziten Sortierstep in ihrer gewünschten Reihenfolge anzeigt. Solche Spielzeuge waren zu FAT Zeiten sehr beliebt, vor allem, um oft gebrauchte Dateien nach vorn zu holen. Dann musst Du ganz anders vorgehen, und dann ist auch die Frage, ob dein Filesystem sowas überhaupt zulässt. Wenn das nicht das Anliegen ist, reicht ein einfacher "rename in place", wie wir ihn bisher diskutieren.

        Die Funktion "glob" liefert Dir, meine ich, keine definierte Reihenfolge. Du müsstest das erhaltene Array also noch sortieren. Bei opendir/readdir bekommst Du eh nur einzelne Dateien, da kannst Du - wenn nötig - gleich auf .mp3 filtern und musst dann auch nochmal sortieren.

        Bei scandir kannst Du eine Reihenfolge angeben. Wenn die Dateien so benannt sind wie Du es im Beispiel geschrieben hast, bekommst Du dann die korrekte Ausgangsbasis, in einem Array. Bei unter 1000 Dateien ist das kein Thema.

        readdir und scandir lesen das ganze Verzeichnis. Filtern auf relevante Dateien musst Du selbst. glob kann auf Dateinamen filtern, sogar mit Patterns:

        $mp3Files = glob("/usr/musik/foo/[0-9][0-9][0-9]*.mp3");
        
        $allFiles = glob("/usr/musik/foo/[0-9][0-9][0-9]*.{mp3,wav,ogg}", GLOB_BRACE);
        

        glob mit GLOB_BRACE wirst Du nicht brauchen, wenn Du nur mp3 Dateien hast. Aber die Einschränkung auf Dateien, die mit 3 Ziffern beginnen, könnte nützlich sein.

        Solange Du keine echten Namensduplikate hast, ist meine "böse Helene" irrelevant und Du kannst einfach durchrennen und die Namen umbauen. Entweder mit explode/implode, wie der Raketenscripter meinte, oder mit einem strpos/strspn/substr Gefummel, wie ich.

        Umbenennen tust Du dann mit rename.

        Rolf

        --
        sumpsi - posui - obstruxi
  4. Also müsste ich die Dateinamen als Liste einlesen,

    anschließend von Anfang bis ersten Leerzeochen gegen eine fortlaufende Zahl austauschen

    und den Dateinamen wieder abspeichern.

    Woran scheitert es bisher?

    1. Hallo Rakete,

      Woran scheitert es bisher?

      Ich glaube gar nicht, dass es scheitert. Irgendwie würde ich das sicher hin bekommen. Ich wollte nur vorab wissen, wie man sowas am sinnvollsten macht.

      Danke für die Links.

      Jörg

    2. Hallo Raketenskripter,

      vorsicht mit explode, es könnte auch eine Datei 222 Günni Gravenreuth geben. Also 2 Leerstellen hintereinander.

      Es mag sein, dass das Entfernen von doppelten Leerstellen nichts schadet, das sollte aber zumindest erwähnt sein.

      Ich hätte vermutlich im klassischen C Stil mit

      $start = 0 + strpos($name, ' ');        // find 1st Space
      $start += strspn($name, ' ', $start);   // skip Spaces
      $newName = sprintf("%03d %s", $ldfNr, substr($oldName, $spacePos));
      

      gearbeitet. Für den Sonderfall, dass $name kein ' ' enthält, kommt FALSE heraus, was sich durch das "0 + ..." zu 0 konvertiert.

      Rolf

      --
      sumpsi - posui - obstruxi
      1. Hallo Raketenskripter,

        vorsicht mit explode, es könnte auch eine Datei 222 Günni Gravenreuth geben. Also 2 Leerstellen hintereinander.

        Egal, sofern es nicht zwischen bisheriger "Nummer" und dem "Titelteil" ist. explode kennt

        s. Handbuch:

        $array = explode ( 
                  string $separator ,
                  string $string , 
                  int $limit = PHP_INT_MAX
        )
        

        Da kann auch eine 2 rein :-)

        https://forum.selfhtml.org/self/2021/jul/06/songs-neu-nummerieren-php/1789999#m1789999

  5. Hi there,

    ich möchte in einem Verzeichnis allen Songs neue Nummern im Dateinamen voranstellen.

    Schau Dir einmal FileNameChange an, damit kann man so ziemlich alles machen, was man bei mehr- und vielfachem Dateien-Umbenennen braucht...

  6. Erstmal danke an alle Mitleser für die Tips und die Hilfe.

    Auch danke an die externen Programmtips, aber es ging mir ja nicht um die Songs alleine, sondern auch darum, wieder Neues in php zu lernen.

    Und ich habe 2 Sachen neu gelernt, die ich zwar schon kannte, aber n icht in ihrer Tiefe:

    glob() und explode()

    glob(), weil ich nicht soweit gedacht hatte, das Suchmuster so genau einzustellen

    explode(), weil ich nicht wußte, dass explode() ein Limit kennt. Sehr genial!

    Und ganz im Sinne des Forums (nicht nur einfach Code abschreiben) möchte ich auch mal meine Lösung zur Diskussion stellen.

    $mp3Files = glob("[0-9][0-9][0-9]*.mp3");
    $i = 0;
    foreach ($mp3Files AS $Song) {
    	$arr_song = explode(" ", $Song, 2);
    	$mp3Files_newName[$i] = sprintf("%04d", $i+1)." ".$arr_song[1];
    	rename($mp3Files[$i],$mp3Files_newName[$i]);
    	$i++;
    }
    echo "feddisch...!";
    

    Die scheint so kurz und einleuchtend. Gibts daran etwas auszusetzen?

    Jörg

    1. Tach!

      Gibts daran etwas auszusetzen?

      Wenn es robust sein soll, fehlt die Behandlung eventueller Fehler bei glob() und rename().

      dedlfix.

    2. Hallo Jörg,

      Gibts daran etwas auszusetzen?

      Eine Menge. Aber wenig von Bedeutung. Kritteln kann man viel, muss man aber nicht. Ich krittele einfach mal was ich nur kann, und was Du davon nicht haben willst, schmeiß einfach weg.

      • wähle die Schreibweise deiner Variablen konsistent.

        • underscored: mp3_files
        • camel case : mp3Files
        • pascal case: Mp3Files

        $Song passt da nicht rein. Namen mit Großbuchstaben vorne sind für Klassen gedacht. Schau Dir mal die PSRs an.

        $mp3Files_newNames ist ein Mix aus Underscore und camelCase, sieht aber irgendwie trotzdem "richtig" aus. Tjaaa. Stures Festhalten an Regeln ist auch nicht immer richtig 😉

      • Andererseits - warum gibt's dieses Array überhaupt? Du verwendest die Namen doch später gar nicht mehr. Dann kann's auch eine Variable $newName sein, die pro Durchlauf wiederverwendet wird.

      • Typangaben vor Variablen - machte man mal, ist eher nicht mehr erwünscht. $arr_song möchte vermutlich lieber $nameParts oder ähnlich heißen.

      • wenn Du sprintf nutzt, dann auch konsequent:

      $mp3Files_newName[$i] = sprintf("%04d", $i+1)." ".$arr_song[1];
      
      // vs 
      
      $mp3Files_newName[$i] = sprintf("%04d %s", $i+1, $arr_song[1]);
      
      • Mach deinen Code robuster. Ein Dateiname wie "007Goldeneye.mp3" schießt dich ab. Du solltest prüfen, ob ein Space da ist, bzw. die Länge von $arr_song $nameParts größer als 1 ist. Ist sie 1, war kein Space drin und Du kannst keine Altnummer entfernen. Nimm dann den kompletten alten Namen.

      • Es ist nicht gut, $mp3Files[$i] als Renamequelle zu nutzen. Du machst eine foreach-Schleife, der Schleifenwert steht in $Song, dann solltest Du den auch verwenden. Dass $Song und $mp3Files[$i] identisch sind, ist eine möglicherweise richtige Annahme, aber wenn dein drei Monate älteres Ich diesen Code vorfindet und sieht, dass Du mal $Song und mal $mp3Files[$i] verwendest, wird es sich fragen: Wieso zum grundgütigen Geier nahm ich erst dies und dann das? Gab's da einen Grund für?!?!?! Und dann wirst Du Dich verfluchen 😉

      Ich hätt's vermutlich so geschrieben:

      $i = 1;
      $mp3Files = glob("[0-9][0-9][0-9]*.mp3");
      if ($mp3Files !== FALSE) {
        foreach ($mp3Files AS $songName) {
          $nameParts = explode(" ", $songName, 2);
          $cleanName = count($nameParts) > 1 ? $nameParts[1] : $songName;
          $newName = sprintf("%04d %s", $i++, $cleanName);
          if (file_exists($newName)) {
            echo "Rename von $songName in $newName nicht möglich. Datei existiert schon.\n";
          }
          else {
            if (!rename($songName, $newName)) {
              echo "Rename von $songName in $newName gescheitert.\n";
            }
          }
        }
      }
      echo "feddisch...!";
      

      Edit: Dedlfixens Robustheitshinweise beachtet. Und vor allem file_exists abgefragt, sonst killt rename die Zieldatei kommentarlos.

      Rolf

      --
      sumpsi - posui - obstruxi
      1. Hi there,

        • Typangaben vor Variablen - machte man mal, ist eher nicht mehr erwünscht.

        Weil? Welchen Nachteil handelt man sich damit ein?

        1. Hallo,

          • Typangaben vor Variablen - machte man mal, ist eher nicht mehr erwünscht.

          Weil? Welchen Nachteil handelt man sich damit ein?

          eigentlich keinen - aber diese Konvention war noch nie sinnvoll. Präfixe an Variablennamen sollten den Verwendungszweck beleuchten, nicht unbedingt den Typ (denn der ergibt sich daraus).

          Live long and pros healthy,
           Martin

          --
          Fische, die bellen, beißen nicht.
        2. Hallo klawischnigg,

          Welchen Nachteil handelt man sich damit ein?

          Eigentlich Redundanz. Im Zweifelsfall zeigt einem die IDE den Typ an. Ich hab's aber nochmal nachgelesen: https://de.wikipedia.org/wiki/Ungarische_Notation

          Was ist ein Typ?

          Charles Simonyi, der diese "Ungarische Notation" erfunden hat, hat gemeint, man sollte über genormte Präfixe den Typ der Variablen kennzeichnen. Die Deppen bei Microsoft haben das bei der Übertragung der Idee von der Office- in die Systems-Abteilung vermasselt. Wie eigentlich immer, wenn Anwendungsentwickler mit Systemprogrammierern reden.

          int iCounter;
          

          So hat Simonyi das nicht gemeint. Dass counter ein int ist, sieht man.

          int cntMarbles;
          HANDLE hCustomerFile;
          

          So war's gedacht: semantische Typen. cntMarbles ist ein Counter für Murmeln (und der geht morgen hoffentlich erfolgreich auf 80000, während cntMarblesOnFloor auf 0 bleibt (Hä?)), und hCustomerFile ist ein Handle für die Kundendatei.

          Deshalb ist $arr_song nicht sinnvoll. "arr" ist ein technischer Typ, kein fachlicher Typ. $cntFiles, $cntNames, $cntQuestions sind Zähler für diverse Dinge, da ist das sinnvoll.

          Rolf

          --
          sumpsi - posui - obstruxi
      2. Hallo Rolf,

        ich freue mich über Deine Kritik und übernehme gerne ein paar Punkte.

        • wähle die Schreibweise deiner Variablen konsistent.

          • underscored: mp3_files
          • camel case : mp3Files
          • pascal case: Mp3Files

        Werde ich versuchen, kann aber nicht dafür garantieren. Habe über die Jahrfe so meine eigene Idee von Variablennamen entwickelt. Ich weiß nicht, ob ich mich da so diszipliniert bekomme.

        $Song passt da nicht rein. Namen mit Großbuchstaben vorne sind für Klassen gedacht. Schau Dir mal die PSRs an.

        Oh. Das kann ich berücksichtigen.

        $mp3Files_newName[$i] = sprintf("%04d %s", $i+1, $arr_song[1]);

        
        

        Was macht das %s genau?

        • Mach deinen Code robuster. Ein Dateiname wie "007Goldeneye.mp3" schießt dich ab.

        Kann nicht vorkommen, aber egal. Finde es trotzdem sinnvoll, was Du sagst.

        • Es ist nicht gut, $mp3Files[$i] als Renamequelle zu nutzen. Du machst eine foreach-Schleife, der Schleifenwert steht in $Song, dann solltest Du den auch verwenden. Dass $Song und $mp3Files[$i] identisch sind, ist eine möglicherweise richtige Annahme, aber wenn dein drei Monate älteres Ich diesen Code vorfindet und sieht, dass Du mal $Song und mal $mp3Files[$i] verwendest, wird es sich fragen: Wieso zum grundgütigen Geier nahm ich erst dies und dann das? Gab's da einen Grund für?!?!?! Und dann wirst Du Dich verfluchen 😉

        Einverstanden. 👍

        Ich hätt's vermutlich so geschrieben:

        
            $cleanName = count($nameParts) > 1 ? $nameParts[1] : $songName;
            $newName = sprintf("%04d $s", $i++, $cleanName);
        

        Ich verstehe nicht ganz, was Du in der ersten zeile prüfst, ich mag dieses Kurzschreibweisen auch nicht.

        Und die ZusaMMENSETZUNG von $newName ist mir auch nicht ganz klar.

        Ansonsten schöner, schlanker Code.

        Jörg

        1. Hallo Jörg,

          du musst wirklich mal anfangen, das PHP-Handbuch zu lesen. Da steht das alles mit Beispielen drin, sogar auf deutsch. Das schreibe ich jetzt nicht ab.

          %s ist für Zeichenketten.

          Ich hatte oben einen Tippfehler drin, da stand $s im Formatstring. Das musste natürlich %s sein.

          Rolf

          --
          sumpsi - posui - obstruxi
        2. Deine Lösung geht soweit durch - solange Du weißt, was Du machst und Backups hast (Das gilt immer, also auch für mein Skript:)

          skript.sh:

          #/bin/bash
          if [ -d $1 ]; then
          	olddir=$(pwd);
          	cd "$1";
          	ls -f -C *.mp3 *.wav | sort -R | awk -f /tmp/test/skript.awk;
          	cd "${olddir}";
          else
          	>&2 echo "Fehler: Kein Verzeichnis angegeben."
          fi
          

          skript.awk:

          {
                  i=i+10;
                  oldname=$0;
                  newname=$0;
                  gsub("^[^ ]+ ", "", newname);
                  newname=sprintf("%05d %s", i, newname);
                  gsub("'", "'\\''", oldname);
                  gsub("'", "'\\''", newname);
                  cmd="mv '"oldname"' '"newname"';";
                  print cmd;
                  #system(cmd);
          }
          
          

          Hints:

          • Zum Ausführen die Raute vor #system(cmd) in der Datei "skript.awk" entfernen.
          • Ich würde in der skript.sh womöglich andere Optionen für sort verwenden: -R „shuffelt“.
      3. Hallo,

        Ich hätt's vermutlich so geschrieben:

        Und ich habs, glaube ich, 1:1 übernommen:

        $path = "C:/Users/My/Downloads/___myMusic/neu";
        
        //$path = "./";
        
        $mp3Files = glob($path."\[0-9][0-9][0-9]*.mp3");
        
        //echo "<pre>";
        //print_r($mp3Files);
        //exit;
        
        
        $i = 1;
        if ($mp3Files !== FALSE) {
          foreach ($mp3Files AS $songName) {
            $nameParts = explode(" ", $songName, 2);
            $cleanName = count($nameParts) > 1 ? $nameParts[1] : $songName;
            $newName = sprintf("%04d %s", $i++, $cleanName);
            if (file_exists($newName)) {
              echo "Rename von $songName in $newName nicht möglich. Datei existiert schon.\n";
            }
            else {
              if (!rename($songName, $newName)) {
                echo "Rename von $songName in $newName gescheitert.\n";
              }
            }
          }
        }
        echo "feddisch...!";
        

        Dabei erhielt ich sofort unzählige "Datei existiert schon" Meldungen und habe, weils nicht weitergung, das Script abgebrochen.

        Ergebnis: Von 340 mühsam gesuchten Songs sind nur noch 26 übrig 😕

        Hab ich ne Chance, die anderen irgendwo noch zu finden oder sind die für ewig weg??

        ich habe sie zwar noch auf Spotity, aber müsste sie alle nochmal konvertieren, also quasi mitschneiden.

        Jörg

        1. Hallo Jörg,

          ich kann keine Garantie für Snippets übernehmen, die ich vom Hirn ins Forum gedumpt habe. Die Verantwortung für Code, den Du laufen lässt, hast Du allein.

          Die erste Frage muss daher leider lauten: hast Du das Script getestet, bevor Du es auf den Originalordner losgelassen hast? Z.B. indem Du ein paar Lieder aus dem Originalordner woandershin kopiert und das Script auf die Kopie geworfen hast?

          Kein Test? Kein Mitleid.

          Die zweite Frage muss lauten: Wo ist dein Backup? Das sollte den Stand vor dem Scriptlauf wiederherstellbar machen. Kein Backup? Kein Mitleid. Hm. Ja. Ich habe auch nicht von allen Dateisammlungen ein ordentliches Backup und verdiente in solchen Fällen deshalb auch kein Mitleid…

          Aber...

          Ergebnis: Von 340 mühsam gesuchten Songs sind nur noch 26 übrig

          Wie kann das sein, wenn (a) das Script keine Löschoperation enthält und (b) im Falle von "Datei existiert schon" nichts tut? Das war ja genau das Problem, auf das Dedlfix hinwies: rename überschreibt die Zieldatei, wenn sie existiert, so dass ein Bug dazu führen kann, dass nachher Dateien fehlen.

          Vielleicht wurden die Dateien auch an einen unerwarteten Ort verschoben. Was war der aktuelle Ordner für das PHP Script, das das angerichtet hat? Liegen die umbenannten Dateien in diesem Ordner? Wenn rename kein Schreibrecht auf den Zielordner hat, sollte es nichts tun. Es hat was getan, also müssen die Dateien irgendwo sein.

          Rolf

          --
          sumpsi - posui - obstruxi
          1. Hi Rolf,

            vorab: Ich hoffe, Du hast mien Post nicht als Vorwurf verstanden, denn ich sehe das genauso, wie Du:

            ich kann keine Garantie für Snippets übernehmen, die ich vom Hirn ins Forum gedumpt habe. Die Verantwortung für Code, den Du laufen lässt, hast Du allein.

            So isses.

            Die erste Frage muss daher leider lauten: hast Du das Script getestet, bevor Du es auf den Originalordner losgelassen hast? Z.B. indem Du ein paar Lieder aus dem Originalordner woandershin kopiert und das Script auf die Kopie geworfen hast?

            Habe ich gemacht. Aber nicht mit den Originaldaten, sondern einer Testliste.

            Die zweite Frage muss lauten: Wo ist dein Backup? Das sollte den Stand vor dem Scriptlauf wiederherstellbar machen. Kein Backup? Kein Mitleid. Hm. Ja. Ich habe auch nicht von allen Dateisammlungen ein ordentliches Backup und verdiente in solchen Fällen deshalb auch kein Mitleid…

            Ich habe sogar ein Backup gemacht. Aufs handy...habe aber vergessen, dass ich inzwischen das Handy hab wechseln müssen 😉

            Aber...

            Ergebnis: Von 340 mühsam gesuchten Songs sind nur noch 26 übrig

            Wie kann das sein, wenn (a) das Script keine Löschoperation enthält und (b) im Falle von "Datei existiert schon" nichts tut? Das war ja genau das Problem, auf das Dedlfix hinwies: rename überschreibt die Zieldatei, wenn sie existiert, so dass ein Bug dazu führen kann, dass nachher Dateien fehlen.

            Vielleicht wurden die Dateien auch an einen unerwarteten Ort verschoben. Was war der aktuelle Ordner für das PHP Script, das das angerichtet hat? Liegen die umbenannten Dateien in diesem Ordner? Wenn rename kein Schreibrecht auf den Zielordner hat, sollte es nichts tun. Es hat was getan, also müssen die Dateien irgendwo sein.

            Mein Retter in der Not... 😀

            Tatsächlich hat das Script fein säuberlich alle Songs wie gewünscht nummeriert ins Scriptverzeichnis verschoben. Die Songs waren auf C:\xyz und das Script lag in Z:\musik.

            OK, so wird ein Schuh draus:

            ich habe kein Zielverzeichnis angegeben, also hat das Script alle Titel ins Scriptverzeichnis geschrieben und da dort bereits die 50 Testeinträge meines Tests lagen, habe ich die Fehlermeldungen bekommen.

            Insofern sind die Songs wohl gerettet, aber ist trotzdem ein wenig doof, weil nun natürlich Doppeleinträge in der Liste sind, weil die Testliste eine Teilliste der Originalliste war.

            Also muss ich jetzt das Script nochmal neu durchlaufen lassen und die Duplikate (die es ja wegen der Nummerierung nicht wirklich sind) heraus filtern. Ach Herrje. 😏

            Jörg

        2. Hi,

          Ergebnis: Von 340 mühsam gesuchten Songs sind nur noch 26 übrig 😕

          Du hast das auf den Original-Ordner losgelassen, nicht auf eine Kopie davon?

          OH-oh.

          Ich mach bei solchen Aktionen auch noch folgendes:

          Beim ersten Rename wird vorne oder hinten an den Dateinamen noch was angehängt, a la "neu" + neuername.

          Damit überschreibe ich auf keinen Fall die Originaldatei - selbst wenn ich keine Sicherheitskopie hab.

          Dann noch ein zweites Scriptlein, das getrennt angestoßen wird (falls das Ergebnis der Erwartung entspricht) und das "neu" wieder wegnimmt.

          Hab ich ne Chance, die anderen irgendwo noch zu finden oder sind die für ewig weg??

          in Deinem Backup.

          cu,
          Andreas a/k/a MudGuard