Wie kann ich alle Dateien aus einem Verzeichnis löschen, wenn "Argumentliste zu lang" gemeldet wird?

11

Ich habe ein Verzeichnis mit ein paar hunderttausend Dateien.

Ich möchte alle Dateien löschen, aber rm * -f meldet: "Argumentliste zu lang"

Was ist der beste Weg, um dieses Verzeichnis zu löschen?

Brent
quelle
Verwandte, semi-duplicate: unix.stackexchange.com/questions/37329/…
Denilson Sá Maia

Antworten:

11

Falls Sie das Verzeichnis nicht entfernen können, können Sie immer find verwenden.

find . -maxdepth 1 -type f -exec rm -f {} \;

Dadurch werden alle Dateien im aktuellen Verzeichnis und nur das aktuelle Verzeichnis (keine Unterverzeichnisse) gelöscht.

skraggy
quelle
fast perfekt (siehe auch meinen Beitrag)
asdmin
2
Unter Linux können Sie dies noch schneller tun, indem Sie "+" anstelle von "\;" verwenden. Dadurch werden mehr Dateien pro "rm" auf einmal entfernt.
Thomas
5
Noch schneller: find dir/to/delete -delete(Spawnt keinen rmProzess pro zu löschender Datei).
Morten Siebuhr
Morten: Er hat nie erwähnt, dass er das Verzeichnis selbst löschen möchte, sagte er nur in den Dateien. find dir/to/delete -type f -delete
Richo
21
finden . -maxdepth 1 -type f -exec rm -f {} \;

es dauert einfach zu lange (eine Ausführung von rm pro Datei).

Dieser ist viel effizienter:

finden . -maxdepth 1 -type f -print0 | xargs -r0 rm -f

Da so viele Dateinamen wie Argumente für rm benötigt werden, wird rm beim nächsten Laden von Dateinamen ausgeführt. Es kann vorkommen, dass rm nur zwei- oder dreimal aufgerufen wird.

asdmin
quelle
5
Ich bin froh zu sehen, dass jemand weiß, wie find funktioniert ... Berücksichtigen Sie auch bei new gnu find die Aktion -delete oder den Befehl -exec {} +, der sich wie xargs verhält. Siehe den Abschnitt Aktionen von 'man find'.
Kyle Brandt
Ich wusste nichts über -exec cmd {} +. Das sieht ziemlich nützlich aus. Etwas allgemeiner als -delete :)
David Pashley
-delete mag in Ordnung sein, aber ich persönlich bevorzuge Befehle, die auf verschiedenen Maschinen verwendet werden können. Solaris-Systeme, mit denen ich arbeite, sind älter, daher würde -delete auf ihnen nicht funktionieren
asdmin
2
Das Hinzufügen ionicekurz zuvor rmist eine gute Idee, wenn der Computer gleichzeitig von anderen Personen verwendet wird.
Hubert Kario
6

Beides wird das Problem umgehen. Es ist eine Analyse der jeweiligen Leistung der einzelnen Technik über hier .

find . -name WHATEVER -exec rm -rf {} \;

oder

ls WHATEVER | xargs rm -rf

Das Problem ergibt sich aus der Bash-Erweiterung "*" mit jedem einzelnen Element im Verzeichnis. Beide Lösungen arbeiten stattdessen nacheinander durch jede Datei.

Coops
quelle
2
Die Suchlösung ist bei vielen Dateien langsamer, da der Befehl rm für jede einzelne Datei aufgerufen wird. Die xargs-Lösung ist schneller, funktioniert jedoch nur, wenn die Dateinamen keine Leerzeichen enthalten (andernfalls benötigen Sie GNU find und find . -print0 | xargs -0 rm).
Robcast
"find. -name WHATEVER -print0 | xargs -0 rm -rf" ist effizienter. find gibt für jede Datei einen rm heraus, wobei xargs ihn auf ein Minimum reduziert. Sie benötigen -print0 und -0, um mit Dateien mit Leerzeichen in fertig zu werden. Sie möchten wahrscheinlich auch -depth für find verwenden, damit eine Tiefensuche durchgeführt wird.
David Pashley
Der Befehl ls funktioniert nicht, da auch dieser "Argumentliste zu lang" zurückgibt
Brent
2
Sie machen " ls *" und das " *" erweitert die Argumentliste, dass Ihre Shell sich darüber beschwert, zu lang zu sein. Führen Sie ls .stattdessen " " aus (oder gehen Sie eine Verzeichnisebene hinauf und tun Sie " ls [dirname]").
James Sneeringer
Die zweite Befehlszeile (ls WHATEVER | xargs rm -rf) würde aus dem gleichen Grund nicht funktionieren wie die Frage nicht: WHATEVER würde durch eine Shell mit einer übermäßigen Länge ersetzt
asdmin
3

Ich konnte dies tun, indem ich eine Ebene sicherte:

cd ..

Und läuft:

rm directory name -rf

Und dann das Verzeichnis neu erstellen.

Brent
quelle
1
Es funktioniert nur, wenn Sie das Verzeichnis nicht dauerhaft haben müssen und alle Dateien und Verzeichnisse rekursiv gelöscht werden sollen. In den meisten Fällen in meinem Leben hätte dieser Weg nicht funktioniert.
Asdmin
2

Alle diese Fundaufrufe sind sehr nett, aber ich erinnere mich selten genau an die Nomenklatur, die ich brauche, wenn ich es eilig habe: Stattdessen benutze ich ls. Wie jemand erwähnt, ls. würde funktionieren, aber ich bevorzuge ls -1 wie in:

ls -1 | xargs -n 100 rm -rf

Die Zahl -n xxx ist ziemlich sicher, da das Überschreiten des Maximums entweder automatisch korrigiert wird (wenn size-max überschritten wird; siehe -s) oder wenn das args-max für eine App überschritten wird, ist dies normalerweise eher der Fall offensichtlich.

Es sollte beachtet werden, dass grep praktisch ist, um es in die Mitte dieser Kette einzufügen, wenn Sie nur eine Teilmenge von Dateien in einem großen Verzeichnis löschen möchten und aus irgendeinem Grund find nicht verwenden möchten.

Bei dieser Antwort wird davon ausgegangen, dass Sie Gnu-Kerndienstprogramme für Ihre ls, xargs usw. verwenden.

Rixtertech
quelle
Funktioniert dies mit einem Verzeichnis, das zu groß ist, als dass "ls" funktionieren könnte? (gleicher Fehler - Argumentationsliste zu lang)
Brent
Ja Brent: Verwenden Sie beim Aufrufen von ls keine Dateispezifikation. Verwenden Sie nur -1 (Bindestrich Eins) wie oben gezeigt. Und wie oben erläutert, verwenden Sie grep nach dem ls, wenn Sie die Dateiliste koppeln müssen. Wenn Sie den Fehler "zu lang" erhalten, nachdem Sie sichergestellt haben, dass Sie keine Platzhalter mit ls verwenden, beschwert sich xargs möglicherweise. Verwenden Sie 'xargs -n 5' anstelle von 'xargs -n 100' und Sie sollten auf jeden Fall sicher sein, wenn auch etwas langsamer.
Rixtertech
1

Sie können die -exec +Option verwenden, um herauszufinden, welche versuchen, rm so oft wie möglich auszuführen, was möglicherweise schneller ist.

find . -type f -exec rm '{}' +
Rory
quelle
0

Hier ist eine Version zum Löschen einer großen Anzahl von Dateien, wenn das System reagieren muss.

Es funktioniert, indem Sie Arbeiten in kleinen Stapeln (standardmäßig 100 Dateien) ausgeben und ein wenig warten, bis andere Jobs abgeschlossen sind.

Hat hervorragend funktioniert, um über eine halbe Million Dateien aus einem einzigen Verzeichnis auf ext3 zu löschen. Der Prozentsatz wird als kleiner Bonus ausgegeben

noOfFiles=`ls -U | wc -l`
n=0
while (ls -U | tail -n 100 | xargs rm -f); do 
   n=$((n+100));
   sync;
   echo -en "$((n*100/noOfFiles))%, ($n of $noOfFiles)\r";
   sleep 5;
done
Hubert Kario
quelle
0

Behebt Fehler "Argument zu lang" oder "Speicher kann nicht zugeordnet werden"

Dies hat den Trick bei mehr als 220.000 Dateien im Sitzungsordner ausgeführt.

Vorteil: Sofortiges Entfernen von Dateien

CD-Pfad / zu / Ordner
ls -f | xargs rm -f -v

KLICKEN Sie für einen Screenshot der zu entfernenden Dateien - (alle Dateien in ~ 15min entfernt)

-f (nach ls) verhindert das Vorsortieren

-v (nach rm) zeigt jede Datei als entfernt an

-f (nach rm) wird ohne Aufforderung für schreibgeschützte Dateien durchgesetzt

Tipp: Benennen Sie zuerst den Ordner (ex session in session_old) um, um zu verhindern , dass zusätzliche automatisch generierte Dateien hinzugefügt werden, während Sie versuchen, Dateien zu löschen. Sie können das ursprüngliche Verzeichnis manuell neu erstellen, wenn dies nicht automatisch der Fall ist, wie in meinem Fall

Kilcode
quelle
Was ist neu in Ihrer Antwort, das in den vorherigen fehlte?
user2233709