Manchmal stößt man auf Linux Verzeichnisse, die so viele Dateien enthalten, dass man sie nicht mehr löschen kann.

Zum Beispiel:

$ rm *
bash: /bin/rm: Argument list too long
$

Dies ist ein Fall für den xargs-Befehl. Mit diesem wenig bekannten Linux-Kommando kann man Befehle für beliebig viele Parameter aufrufen. Der auszuführende Befehl wird - ggf. mit weiteren Parametern - seinerseits dem xargs-Befehl als Parameter übergeben. Alle zusätzlichen Parameter, wie z.B. ein paar hunderttausend zu löschende Dateinamen, liest xargs dann von stdin ein. Der Befehl wird dann nur mit sovielen Parametern aufgerufen, wie unter Linux zulässig ist. Falls in der Kommandozeile auch weitere Parameter angegeben wurden, dann werden diese Parameter ebenfalls verwendet, die zusätzlichen Parameter von stdin kommen immer danach.

Konkret sieht das so aus:

$ find . | xargs rm

Der find . Befehl listet alle Dateien im aktuellen Verzeichnis. Durch das Pipe-Symbol wird das Listing dem xargs-Kommando übergeben, welches dann seinerseits das rm-Kommando ggf. mehrfach aufruft.

Kopieren

Etwas schwieriger ist das Kopieren von sehr vielen Dateien in ein Ziel-Directory. Wenn man find . | xargs cp (Ziel) eingibt, funktioniert es nicht wie erhofft, da ja die Parameter für die zu kopierenden Dateien angehängt werden, d.h. das Ziel-Verzeichnis ist der erste Parameter und nicht der letzte.

Glücklicherweise gibt es für die cp- oder mv-Befehle den Parameter -t oder --target-directory=. Die korrekte Syntax sieht also so aus:

$ find . | xargs cp --target-directory=/home/mydata

Kopieren von Dateien mit Leerzeichen

Richtig interessant wird es, wenn man Dateien kopieren will, die Leerzeichen oder andere spezielle Zeichen enthalten. Leerzeichen werden von xargs nämlich als Trennzeichen aufgefasst:

$ ls -la
total 8
drwxr-xr-x  2 u00 u00 4096 Feb 27 18:39 .
drwxr-xr-x 12 u00 u00 4096 Feb 27 18:38 ..
-rw-r--r--  1 u00 u00    0 Feb 27 18:39 Datei eins
-rw-r--r--  1 u00 u00    0 Feb 27 18:39 Datei zwei
$ find . -type f | xargs ls -l
ls: ./Datei: No such file or directory
ls: eins: No such file or directory
ls: ./Datei: No such file or directory
ls: zwei: No such file or directory

Um dies zu umgehen, kann man xargs veranlassen, das NUL-Zeichen (hexadezimal 0x00) als Trennzeichen zu verwenden. Natürlich muss das Programm, welches die Parameterliste generiert, ebenfalls das NUL-Zeichen verwenden.

Bei find sieht das dann so aus:

$ find . -print0 -type f | xargs -0 ls -l
-rw-r--r-- 1 u00 u00    0 Feb 27 18:39 ./Datei eins
-rw-r--r-- 1 u00 u00    0 Feb 27 18:39 ./Datei zwei

Falls das Tool keine Option -0 hat, muss man on-the-fly die NUL-Zeichen einbauen. Man ersetzt z.B. die Line Feeds mit Hilfe eines regulären Ausdrucks, am besten mit Perl:

$ find . -type f | perl -pe 's,\n,\0,' | xargs -0 ls -l
-rw-r--r-- 1 u00 u00    0 Feb 27 18:39 ./Datei eins
-rw-r--r-- 1 u00 u00    0 Feb 27 18:39 ./Datei zwei

Related articles

Unbedingt das Label kb-how-to-article aus dem nachfolgenden Macro löschen.

Related issues
To Do