ich habe einen Ordner namens „Test“, der nur JPEG-Dateien enthält. Tausende von Dateien. Ich muss diese Tausenden von Dateien, die Namen wie 1.jpg, 2.jpg ... 345623.jpg haben, in Unterordner mit Namen wie 001000, 002000 verschieben, die jeweils 1000 Dateien enthalten. Ich muss also alle JPG-Dateien aus dem Testordner auf die leistungsstärkste und effizienteste Weise in Unterordner verschieben, die jeweils 1000 JPG-Dateien enthalten.
Was ich bisher habe, ist:
i=1;while read l;do mkdir $i;mv $l $((i++));done< <(ls|xargs -n1000)
Antwort1
find . -type f \
| split -l 1000 -a 3 --numeric-suffixes=1 \
--filter='target="${FILE}000"; mkdir "$target" && xargs -d "\n" mv -t "$target"' \
- ''
Erläuterung:
find . -type f
findet Dateien (auch in Unterverzeichnissen, aber ich glaube, in deinem Fall gibt es noch keine Unterverzeichnisse).split -l 1000 -a 3 --numeric-suffixes=1 ... - ''
liest von seinem Standardeingang (-
) und teilt die Daten in Blöcke auf, wobei jeder Block 1000 Zeilen lang ist (-l 1000
). Jedem Block wird ein „Name“ zugeordnet, der aus dem leeren Präfix (''
) und einem numerischen Suffix, beginnend bei 1 (--numeric-suffixes=1
), mit einer Länge von 3 (-a 3
) besteht. Tatsächlich lauten die Namen an dieser Stelle001
,002
und so weiter.--filter=...
führt den angegebenen Befehl für jeden Chunk separat aus, der jeweilige Name steht als$FILE
. Der auszuführende Befehl lautettarget="${FILE}000"; mkdir "$target" && xargs -d "\n" mv -t "$target"
target="${FILE}000"
wandelt den Namen beispielsweise001
oder002
in den gewünschten zukünftigen Verzeichnisnamen (001000
oder002000
usw.) um und speichert diesen in dertarget
Variablen.mkdir "$target"
erstellt ein neues Verzeichnis mit dem gewünschten Namen.xargs -d "\n" ...
liest den gesamten Block (1000 Dateipfade oder weniger im letzten Block) und verwendet jede ganze Zeile (neue Zeile als Trennzeichen:-d "\n"
) als Argument für den folgenden Befehl.mv -t "$target"
verschiebt Objekte (übergeben vonxargs
) in das neu erstellte Verzeichnis.
Anmerkungen:
- Der Befehl kümmert sich nicht um Dateinamen.
345623.jpg
endet nicht unbedingt in346000/
. Mögliche Gründe:find
sortiert nicht; aber selbst wenn Siesort -n
zwischenfind
und setzensplit
, kann es sein ...- es gibt Lücken in der Nummerierung.
split
benötigt in jedem Fall 1000 Einträge (außer es handelt sich um den letzten Block; in diesem Fall 1000 oder weniger).
mkdir ... && xargs ...
xargs
wird bei einem Fehler nicht ausgeführtmkdir
(Vorsicht bei vorhandenen Verzeichnissen).- Verwenden Sie
cp -l -t "$target"
anstelle vonmv -t "$target"
, um Hardlinks in Verzeichnissen zu erstellen, wobei bereits vorhandene Einträge im aktuellen Verzeichnis intakt bleiben. Auf diese Weise können Sie, falls etwas schief geht, einfachrm -r
die Verzeichnisse verschieben und von vorne beginnen.mv
Wenn Sie die Aufgabe mit unterbrechen, werden am Ende einige Dateien verschoben, andere nicht; das kann ein Chaos sein. - Ich glaube,
-a 3
Sie kommen damit nicht weiter999
(999000
nach dem Anhängen von Nullen am Ende). Wennsplit
weitere Chunks erstellt werden müssen, schlägt dies mitten im Job fehl. Stellen Sie deshalb sicher, dass999
genug vorhanden ist, bevor Sie den Befehl ausführen. - Namen mit Zeilenumbrüchen beschädigen den Code (im Allgemeinen sehen Ihre Dateinamen gut aus).