Ordnernamen dem Dateinamen voranstellen und die Dateistruktur glätten

Ich habe zum Beispiel eine Reihe von Ordnern mit verschiedenen Namen

2013-02   Snow and birds
    PICT0001.jpg
    PICT0002.jpg
2013-06   Bicycle trip
    edited_panorama.jpg
    From phone
        DCIM0001.jpg
        DCIM0002.jpg
        DCIM0003.jpg
    From camera
        DSLR
            PICT0001.raw
            PICT0002.raw
        Compact
            S0000001.jpg           

Wie Sie sehen können, besteht die allgemeine Struktur aus einer unterschiedlichen Ebene verschachtelter Unterordner, die Bilder enthalten. Was ich tun möchte, ist, die Struktur zu verflachen, indem ich den Namen jeder Ebene von Unterordnern zum Dateinamen hinzufüge, wie folgt:

2013-02   Snow and birds_PICT0001.jpg
2013-02   Snow and birds_PICT0002.jpg
2013-06   Bicycle trip_edited_panorama.jpg
2013-06   Bicycle trip_From phone_DCIM0001.jpg
2013-06   Bicycle trip_From phone_DCIM0002.jpg
2013-06   Bicycle trip_From phone_DCIM0003.jpg
2013-06   Bicycle trip_From camera_DSLR_PICT0001.raw
2013-06   Bicycle trip_From camera_DSLR_PICT0002.raw
2013-06   Bicycle trip_From camera_Compact_S0000001.jpg

Wie kann dies erreicht werden, indem entweder ein Terminal-Skript oder eine andere Art von Skript verwendet wird? Ich habe einige ähnliche Lösungen gefunden, aber sie scheinen alle auf einer festen Ebene von Unterordnern zu beruhen, während meine Ordnerstruktur variiert.

Antworten (3)

Schwierig, besonders wenn Sie alle Leerzeichen usw. behalten möchten. Führen Sie Folgendes im obersten Verzeichnis aus (dasjenige, das 2013-02 Snow and birdsusw. enthält):

find . -type f -exec sh -c 'for f do x=${f#./}; echo mv "$x" "${x////_}"; done' {} +

Die Zuweisung an xbeseitigt das führende ./from find, das ${x////_}ersetzt alle (verbleibenden) Vorkommen von /durch _.

mvAußerdem habe ich das aktuelle mit einem geschützt, echodamit Sie zuerst überprüfen können, ob die Befehle in Ordnung aussehen. Führen Sie den Befehl erneut aus, ohne echodie Dateien tatsächlich umzubenennen/zu verschieben.

Hat super funktioniert! Obwohl aus unerklärlichen Gründen 3 von 8300 Dateien fehlten. Glücklicherweise habe ich nach dem Verschieben der Dateien alle Ordner und Unterordner erweitert, nur um sicherzugehen! Die 3 Dateien waren alle nur 1 Ebene tief und in Ordnern verschachtelt, in denen zuvor andere Dateien mit ähnlichen Namen (PICT0001.JPG usw.) waren.
@nohillside Danke für die Bereitstellung dieses Befehls! Gibt es eine Möglichkeit, dies zu ändern, sodass die Dateien nicht aus ihren ursprünglichen Ordnern verschoben werden?
@Philipp Die ganze Idee hier ist, die Dateien aus ihren ursprünglichen Ordnern zu verschieben. Wenn Sie ein anderes Problem haben, das Sie lösen möchten, stellen Sie bitte eine neue Frage.

Die Antwort von @nohillside oben ist eigentlich großartig. Das einzige Problem dabei ist, dass Dateien mit Leerzeichen nicht berücksichtigt werden. Das führt dazu, dass einige der Befehle fehlschlagen.

Also stelle ich hier eine Antwort, die dies ebenfalls unterstützen würde.

Dies wird nur die Befehle echoausgeben :mv

find . -type f -exec sh -c 'for f do x=${f#./}; y="${x// /_}"; echo "mv ${x// /\ } ${y////-}"; done' {} +

Dadurch werden echodie mvBefehle direkt in Ihre Zwischenablage ausgegeben:

find . -type f -exec sh -c 'for f do x=${f#./}; y="${x// /_}"; echo "mv ${x// /\ } ${y////-}"; done' {} + | pbcopy

[Vorsicht] Dadurch werden die mvBefehle sofort für Sie ausgeführt:

find . -type f -exec sh -c 'for f do x=${f#./}; y="${x// /_}"; eval "mv ${x// /\ } ${y////-}"; done' {} +
Jetzt bin ich neugierig :-) Welches spezifische Szenario mit Leerzeichen lässt mein Code-Snippet fehlschlagen?
Nur wenn der Dateiname Leerzeichen enthält. Es maskiert die Leerzeichen im so nicht echomit einem direkten Kopieren und Einfügen, es funktioniert für die meisten Dateien, außer für diejenigen, die den Fehler ausspucken, der die Verwendung von mv erklärtusage: mv [-f | -i | -n] [-v] source target
Nun, die Idee ist nicht, das Ergebnis zu kopieren/einzufügen, sondern das Echo zu entfernen, sobald die Ausgabe in Ordnung aussieht. Aber wie immer gibt es viele Möglichkeiten :-)
Es gibt ein Problem mit eval unter MacOS, wenn der Bildname Klammern enthält: Image(30).jpg: eval: line 0: syntax error near unknown token `('

Für die Zwecke dieses Skripts hatte ich alle Ihre Ordner in einem Ordner namens „Filez“ auf meinem Desktop. Dieses Skript beginnt mit einem "Ordner auswählen"-Dialog, um den übergeordneten Ordner auszuwählen, in dem sich die Ordner "2013-06 Fahrradreise" und "2013-02 Schnee und Vögel" befinden. Dadurch werden alle einzelnen Dateien in allen Ordnern und Unterordnern zurückgegeben, deren Namen geändert werden sollen.

set mainFolder to choose folder
set posixPathOfMainFolder to POSIX path of mainFolder
tell application "Finder"
    set theNames to files of entire contents of mainFolder as alias list
end tell
set newFileNames to {}
repeat with aFile in theNames
    set text item delimiters to {posixPathOfMainFolder, "/"}
    set aFile to POSIX path of aFile
    set tempName to text items -1 thru 2 of aFile
    set text item delimiters to "_"
    set end of newFileNames to tempName as text
    set text item delimiters to ""
    tell application "Finder"
        set the name of (aFile as POSIX file as alias) to last item of newFileNames as text
    end tell
end repeat
tell application "Finder"
    set theNames to files of entire contents of mainFolder as alias list
    move theNames to mainFolder
    delete folders of mainFolder
end tell

Geben Sie hier die Bildbeschreibung ein