Versuchen:
find . -mindepth 2 -type f -name '*.pdf' -exec bash -c 'f=$; mv "$1" "./$"' None {} \;
Dies ist sicher für alle Dateinamen, auch für Dateinamen, deren Namen Zeilenumbrüche enthalten.
Wie es funktioniert
-mindepth 2
Dies weist find an, keine Dateien zu verarbeiten, die sich bereits im aktuellen Verzeichnis befinden.
-type f -name '*.pdf'
Dies beschränkt die Suche auf reguläre Dateien mit der
pdf
Erweiterung.-exec bash -c '...' None {} \;
Dadurch wird der Befehl in der in Anführungszeichen stehenden Zeichenfolge ausgeführt, wobei der Dateiname als erstes Argument angegeben wird
$1
.Für unsere Zwecke ist die Zeichenfolge
None
einfach ein Platzhalter. Es wird zugewiesen$0
, unter bash Konventionen, ist der Name des Befehls, wir laufen.f=$; mv "$1" "./$"
(A) entfernt das Präfix
./
vom Dateinamen und (b) verschiebt die Datei an den gewünschten Ort mit dem neuen Namen.$
ist ein Beispiel für die Entfernung von bash Präfixen . Es gibt die strign$1
mit./
von Anfang an entfernt.$
ist ein Beispiel für die Mustersubstitution von bash . Es gibt den String zurück,$f
wobei alle mit/
ersetzt werden_
. Um mehr über diese Funktionen zu lesen, finden Sie im Abschnitt in demman bash
Titel Parameter Expansion .
Effizientere Version
Die obige Version ruft bash für jede gefundene Datei auf. Alternativ können Sie bash nur einmal für mehrere gefundene Dateien aufrufen. Dazu wickeln wir unseren Befehl in eine for
Schleife:
find . -mindepth 2 -type f -name '*.pdf' -exec bash -c 'for f in "$@"; do f=$; echo mv "$f" "./$"; done' None {} +
Alternatives Problem
Angenommen, alle Dateien, die wir benötigen, befinden sich in einem Verzeichnis der zweiten Ebene, und wir möchten, dass die verschobenen Dateien in der Reihenfolge der Verzeichnisnamen umgekehrt werden, so dass ./path1_pathA_fileI.pdf
wir statt mit enden ./pathA_path1_fileI.pdf
. In diesem Fall:
for d1 in */; do d1=$; for d2 in "$d1"/*/; do d2=$; p="$_$d1"; for f in "./$d2"/*.pdf; do echo mv "$f" "./$_$"; done; done; done
Oder für diejenigen, die es bevorzugen, dass ihre Befehle über mehrere Zeilen verteilt sind:
for d1 in */ do d1=$ for d2 in "$d1"/*/ do d2=$ p="$_$d1" for f in "./$d2"/*.pdf do echo mv "$f" "./$_$" done done done