Wie kann ich Dateien mit Whitespace rekursiv entfernen?

7813
Dr Beco

Ich habe Probleme mit diesem Befehl unter bash in Ubuntu:

rm $(find . -name "*.exe") 

Mein Ziel ist es, rekursiv alle Dateien zu entfernen, die auf enden .exe. Einige Dateien haben jedoch Leerzeichen, und der Befehl wird unterbrochen.

Anregungen, wie Sie dieses Problem angehen können?

5

4 Antworten auf die Frage

16
Jonathan Leffler
find . -name "*.exe" -exec rm -f '{}' + 

Dies hat findden Befehl und die Argumente formatiert, und es wird sorgfältig vermieden, die Namen zu manipulieren (indem jeder als separates Argument an übergeben wird rm). Das "+" bedeutet "tun Sie so viele, wie Sie in einer Ausführung von vernünftigerweise können rm".

`find (1)` hat die Aktion `-delete` (möglicherweise nur GNU find), die alle Unterprozesse und umständliche Befehlszeilenoptionen speichert. `finden. -name '* .exe' -delete` camh vor 12 Jahren 3
@camh: Folgen Sie dem Link zur POSIX-Dokumentation. "-delete" ist nicht enthalten. Es ist in GNU `find`; Die Frage ist für Linux. Es ist also möglich, -delete zu verwenden. Allerdings ist nicht die ganze Welt Linux und eine tragbare Antwort kann nützlich sein. Jonathan Leffler vor 12 Jahren 0
3
intuited

Sie können die Ausgabe von findin xargs, unter Angabe, dass nur Zeilenumbrüche als Trennzeichen zwischen Dateinamen berücksichtigt werden sollen:

find -name '*.exe' | xargs -d \\n rm 

Der tragbarere Weg, dies zu tun, ist die Verwendung des Nullzeichens als Trennzeichen:

find -name '*.exe' -print0 | xargs -0 /bin/rm 

Siehe finddie Manpage für ein Beispiel, das dies tut.

Eine andere Option besteht darin, den Befehl zu verwenden, den Sie verwendet haben, aber um das interne Argumenttrennzeichen von bash auf Nur Zeilenumbrüche festzulegen:

IFS=$'\n'; rm $(find . -name "*.exe"); 

Hier wird das $'...'Zitatkonstrukt verwendet, um ein Zeilenvorschubzeichen zu erstellen. Dieser Ansatz ist bei einer langen Liste von Dateinamen weniger belastbar als bei Verwendung von xargs.

Es hat keinen wirklichen Sinn, etwas anderes als die Optionen "-print0" und "-0" zu verwenden. Die andere Funktion funktioniert nicht ordnungsgemäß, wenn die Namen Zeilenumbrüche enthalten (und dies ist ein gültiges Zeichen in einem Unix-Dateinamen). Ähnlich beim IFS-Hack. Beachten Sie, dass dies GNU-spezifische (wenn auch ausgesprochen sinnvolle) Erweiterungen des Standards sind. Jonathan Leffler vor 12 Jahren 1
@Jonathan: Ich benutze normalerweise `-d ', nur weil es weniger tippt, und in der Praxis enthalten Dateinamen (zumindest für mich) niemals neue Zeilen. Es gibt auch den Vorteil, dass Sie die Ausgabe von `find 'durch andere Programme (grep, tail usw.) filtern können, bevor Sie sie an` xargs` senden. intuited vor 12 Jahren 0
1
mainzelM

Übergeben Sie einfach die -deleteOption an find:

find . -name "*.exe" -delete 

Dies erspart Ihnen das Zitieren und alle anderen Probleme mit Dateinamen und ist vermutlich schneller als -execweil keine neuen Prozesse erzeugt werden müssen.

0

Das manuelle Fliehen der Charaktere kann Ihnen helfen.

find . -name "*.exe" | sed -s 's/\ /\\ /' | xargs rm -f 
Keine verlässliche Technik; Ansonsten trennen `xargs 'Namen nach Leerzeichen. Sie könnten `find verwenden. -name "* .exe" -print0 | xargs -0 rm -f`, wobei `-print0` Dateinamen mit ASCII NUL beendet und` -0` bedeutet, dass `xargs` Namen liest, die mit ASCII NUL enden. Beachten Sie, dass dies GNU-spezifische (wenn auch ausgesprochen sinnvolle) Erweiterungen des Standards sind. Jonathan Leffler vor 12 Jahren 0
@Jonathan True .. Ihre Antwort ist definitiv besser. vor 12 Jahren 0