Eine andere Antwort ist, xargs zu erzwingen um die Befehle stapelweise abzuarbeiten. Zum Beispiel an delete die Dateien 100 jeweils cd in das Verzeichnis und führen Sie Folgendes aus:
echo *.pdf | xargs -n 100 rm
tl;dr
Es ist eine Kernel-Beschränkung für die Größe des Befehlszeilenarguments. Verwenden Sie einen for Schleife statt.
Ursprung des Problems
Dies ist ein Systemproblem im Zusammenhang mit execve und ARG_MAX Konstante. Dazu gibt es reichlich Dokumentation (siehe man execve, debian's wiki, ARG_MAX details).
Grundsätzlich erzeugt die Erweiterung einen Befehl (mit seinen Parametern), der ARG_MAX überschreitet limit.On Kernel 2.6.23 , wurde das Limit auf 128 kB gesetzt . Diese Konstante wurde erhöht und Sie können ihren Wert erhalten, indem Sie Folgendes ausführen:
getconf ARG_MAX
# 2097152 # on 3.5.0-40-generic
Lösung:Verwenden von for Schleife
Verwenden Sie einen for Schleife, wie es auf BashFAQ/095 empfohlen wird, und es gibt keine Begrenzung außer für RAM/Speicherplatz:
Testlauf, um sicherzustellen, dass das gelöscht wird, was Sie erwarten:
for f in *.pdf; do echo rm "$f"; done
Und führen Sie es aus:
for f in *.pdf; do rm "$f"; done
Auch dies ist ein portabler Ansatz, da glob ein starkes und konsistentes Verhalten zwischen Shells hat (Teil der POSIX-Spezifikation).
Hinweis: Wie in mehreren Kommentaren angemerkt, ist dies in der Tat langsamer, aber wartungsfreundlicher, da es komplexere Szenarien anpassen kann, z. B. wo man mehr als nur eine Aktion machen will.
Lösung:Verwenden von find
Wenn Sie darauf bestehen, können Sie find verwenden aber wirklich benutze keine xargs da es "gefährlich (kaputt, ausnutzbar usw.) ist, wenn Eingaben gelesen werden, die nicht durch NUL getrennt sind" :
find . -maxdepth 1 -name '*.pdf' -delete
Mit -maxdepth 1 ... -delete statt -exec rm {} + erlaubt find um die erforderlichen Systemaufrufe einfach selbst auszuführen, ohne einen externen Prozess zu verwenden, daher schneller (dank @chepner-Kommentar).
Referenzen
- Ich erhalte "Argument list too long". Wie kann ich eine große Liste in Blöcken verarbeiten? @ wollrand
- execve(2) - Linux-Manpage (Suche nach ARG_MAX);
- Fehler:Argumentliste zu lang @ Debians Wiki;
- Warum erhalte ich „/bin/sh:Argument list too long“, wenn ich Argumente in Anführungszeichen übergebe? @ SuperUser
find hat einen -delete Aktion:
find . -maxdepth 1 -name '*.pdf' -delete
Der Grund dafür ist, dass Bash das Sternchen tatsächlich auf jede passende Datei erweitert, wodurch eine sehr lange Befehlszeile entsteht.
Versuchen Sie Folgendes:
find . -name "*.pdf" -print0 | xargs -0 rm
Warnung: dies ist eine rekursive Suche und findet (und löscht) auch Dateien in Unterverzeichnissen. -f anheften auf den Befehl rm nur, wenn Sie sicher sind, dass Sie keine Bestätigung wünschen.
Sie können Folgendes tun, um den Befehl nicht rekursiv zu machen:
find . -maxdepth 1 -name "*.pdf" -print0 | xargs -0 rm
Eine weitere Option ist die Verwendung von -delete von find Flagge:
find . -name "*.pdf" -delete