Ich führe MacOS in einem Terminal aus, das im Wesentlichen BSD ist, und poste meine Frage daher hier statt bei askdifferent. Ich möchte meinen Bilddatensatz in den folgenden Schritten reduzieren, indem ich Dateien nach dem Zufallsprinzip lösche. Einige Verzeichnisse enthalten über 1 Million JPGs. Meine Daten befinden sich im Hauptverzeichnis mit Unterverzeichnissen, die nur eine maximale Tiefe von 1 haben:
-master
-data1
image.jpgs
-data2
image.jpgs
-data3
image.jpgs
-data4
image.jpgs
... and so forth
Ich habe diesen Link gefunden:
https://superuser.com/questions/1186350/delete-all-but-1000-random-files-in-a-directory
... und kam zu folgendem Ergebnis:
for f in *.jpg; do find "$f" -type f -print0 | sort -R | tail -n +50001 | xargs -0 rm; done
Obwohl es funktioniert, möchte ich, dass es dies rekursiv für Unterverzeichnisse tut, damit ich es nicht für jedes Verzeichnis manuell tun muss. Meine Fragen/Anfragen sind also:
- Kann ich dies irgendwie optimieren, um es zu beschleunigen?
- Gibt sort/tail einen Fehler zurück, wenn es auf ein Verzeichnis mit weniger als 50.000 Dateien stößt?
Antwort1
Nachdem ich den verlinkten Quellbeitrag geprüft habe, sieht es so aus, als ob Ihre Schleife eigentlich wie folgt aussehen sollte:
for d in */; do find "$d" -iname '*.jpg' -type f -print0 | sort -zR | tail -zn +50001 | xargs -0r rm; done
Soll aus dem master
Verzeichnis ausgeführt werden.
Die -z
Optionen für sort
und tail
sind notwendig, da die Eingabe durch Nullen getrennt ist. Keiner von beiden beschwert sich, wenn weniger als 50.000 Zeilen vorhanden sind – sort
es ist egal und tail
es wird nichts ausgegeben, da nach der 50.000. Zeile nichts mehr kommt. rm
könnte sich beschweren, wenn es ohne Argumente ausgeführt wird, aber die -r
Option für GNU xargs
verhindert die Ausführung, rm
wenn es keine Eingabe erhält (BSD xargs benötigt es nicht, wird sich aber wahrscheinlich nicht beschweren).
Zu guter Letzt, aber am wichtigsten, -z
wird die Option für nullbegrenzte Eingaben wahrscheinlich nicht von BSD Tail unterstützt. Sie benötigen GNU Tail, das mit Homebrew installiert werden kann.
Sie könnten wahrscheinlich auf durch Nullen getrennte Zeilen verzichten, wenn Ihre Dateinamen garantiert keine Leerzeichen, Zeilenumbrüche, Anführungszeichen, Backslashs usw. enthalten. In diesem Fall:
for d in */; do find "$d" -type f | sort -R | tail -n +50001 | xargs rm; done