
Test Umgebung:
- Erstellen Sie Verzeichnisse von
0
bis9
und füllen Sie sie mit Dateien vona
bisz
$ mkdir {0..9} && touch {0..9}/{a..z}
- Ergebnis von
find
:$ find -type f ./0/a ./0/b ... ./9/y ./9/z
Wie kann ich die Ausgabe so umwandeln, dass sie folgendermaßen aussieht:
./0a
./0b
...
./9y
./9z
Antwort1
Mit dem eigenständigen Befehl von Perl rename
:
rename -n 's|/||' */*
Wenn alles in Ordnung aussieht, entfernen Sie es -n
und löschen Sie anschließend die verbleibenden leeren Verzeichnisse.
rmdir {0..9}
Antwort2
Mit POSIX-Tools
find . -type f -exec sh -c 'for f; do dirn="${f%/*}"; mv -- "$f" "$dirn${f##*/}"; done' sh {} +
find
ruft eine Shell auf und führt die For-Schleife für jede Datei aus.
dirn="${f%/*}"
ruft den Namen des übergeordneten Verzeichnisses ab, indem alles ausgeschlossen wird, was nach dem letzten Schrägstrich im Dateinamen steht (und diesen einschließt).${f##*/}
ruft den Dateinamen ohne Pfad ab, indem alles ausgeschlossen wird, was vor (einschließlich) dem letzten Schrägstrich im Dateinamen steht.
Diese beiden Schalenkonstrukte tun dasselbe wiedirname
Undbasename
, daher lautet eine äquivalente Form des Befehls
find . -type f -exec sh -c 'for f; do mv -- "$f" "$(dirname "$f")$(basename "$f")"; done' sh {} +
, obwohl dieser langsamer sein sollte, da er für jede Datei zwei zusätzliche Prozesse starten muss.
Wenn Sie nicht in mehr als ein Verzeichnis wechseln müssen, wie in Ihrem Beispiel, genügt eine einfache Shell-Schleife:
for f in */*; do dirn="${f%/*}"; echo mv -- "$f" "$dirn${f##*/}"; done