AA_123rf_21887655_Maksim_Shebeko.jpg

© Maksim Shebeko, 123RF

Mit Xargs Ausgaben zum Weiterverarbeiten aufbereiten

Häppchenweise

Sonderzeichen in Dateinamen bereiten vielen Shell-Tools Probleme. Mit Xargs umschiffen Sie die Hürden elegant.

Komplexe Befehle auf der Kommandozeile erfordern es häufig, die Ausgabe eines Befehls als Eingabe für einen anderen zu verwenden. Ein ganz typisches Beispiel ist das Kommando find: Es listet rekursiv alle den Parametern entsprechenden Dateien auf. So findet der Befehl aus Listing 1 alle Ogg-Vorbis-Dateien im Ordner Podcasts.

Listing 1

$ find Podcasts -name '*.ogg'
Podcasts/dh-20130204-ausgabe-045.ogg
Podcasts/dh-20130107-ausgabe-044.ogg

Möchten Sie nur wissen, ob es sich dabei wirklich ausschließlich um Ogg-Vorbis-Dateien handelt, so prüfen Sie dies mit dem Befehl file nach. Er erhält die Namen der Dateien als Parameter – im Beispiel zwar nur zwei, doch das Tippen der entsprechenden Befehle macht dennoch Arbeit. Dabei gibt es doch die verkehrten Anführungszeichen, englisch "Backticks". Die Ausgabe des Befehls zwischen den Backticks ergibt dabei den Parameter für den äußeren Befehl (Listing 2).

Listing 2

$ file `find Podcasts -name '*.ogg'`
Podcasts/dh-20130204-ausgabe-045.ogg: Ogg data, Vorbis audio, stereo, 44100 Hz, ~91840 bps
Podcasts/dh-20130107-ausgabe-044.ogg: Ogg data, Vorbis audio, stereo, 44100 Hz, ~91840 bps

Stolperfallen

So weit, so gut. Die Funktion trennt die Ausgabe des inneren Befehls an sämtlichen Leerzeichen, inklusive Zeilenumbruch und Tabulator. Das schreit nach der Frage, was passiert, wenn find eine Datei herauspickt, die Leerzeichen im Dateinamen hat. Die Antwort darauf zeigt Listing 3.

Listing 3

$ find Musik -name '*.ogg'
Musik/Roxette - June Afternoon.ogg
Musik/Roxette - I Don't Want to Get Hurt.ogg
$ file `find Musik -name '*.ogg'`
Musik/Roxette: ERROR: cannot open `Musik/Roxette' (No such file or directory)
^C

Mehrere Dinge spielen sich dabei ab: Die Shell hat die Dateinamen an den Leerzeichen aufgetrennt und jeden Teil für sich als einzelnen Parameter verwendet. Das Minuszeichen im Dateinamen übergibt sie ebenfalls als einzelnen Parameter. Der Befehl file interpretiert dies derart, dass er von da ab auf der Standardeingabe auf Daten wartet, um diese zu analysieren. Im vorliegenden Fall bleibt nichts anderes übrig, als den "hängenden" Befehl mit [Strg]+[C] abzubrechen.

Eine weitere Stolperfalle taucht auf, wenn Sie Backticks verschachteln möchten. In der Praxis passiert dies, wenn Sie zuerst alle Verzeichnisse auflisten, die Sie durchsuchen möchten. Listing 4 zeigt ein Kommando, das alle Verzeichnisse durchforstet, die Podcasts heißen.

Listing 4

$ file `find \`find . -name Podcasts -type d\` -name '*.ogg'`
./lang/Podcasts/dh-20130204-ausgabe-045.ogg: Ogg data, Vorbis audio, stereo, 44100 Hz, ~91840 bps
./lang/Podcasts/dh-20130107-ausgabe-044.ogg: Ogg data, Vorbis audio, stereo, 44100 Hz, ~91840 bps
./kurz/Podcasts/dh-20121015-kurz-018.ogg:    Ogg data, Vorbis audio, stereo, 44100 Hz, ~91840 bps

Backticks erlauben es zwar, Kommandos zu verschachteln, aber Sie müssen einen verkehrten Schrägstrich, englisch Backslash, vor die inneren Backticks stellen, damit die Shell sie nicht als schließendes Element zum ersten Backtick ansieht. Spätestens noch eine Ebene tiefer gerät die Sache meist außer Kontrolle: Sie müssten dann den zweiten Backslash noch mit einem dritten Rückstrich maskieren.

Die schnelle Lösung hierfür lautet, das Konstrukt $(...) anstatt Backticks zu verwenden, da diese Variante durch unterschiedliche Zeichen am Anfang und Ende deutlich übersichtlicher ausfällt (Listing 5). Das Problem mit den Leer- und Sonderzeichen in Dateinamen sind Sie damit aber noch nicht los.

Listing 5

$ file $(find $(find . -name Podcasts -type d) -name '*.ogg')
./lang/Podcasts/dh-20130204-ausgabe-045.ogg: Ogg data, Vorbis audio, stereo, 44100 Hz, ~91840 bps
./lang/Podcasts/dh-20130107-ausgabe-044.ogg: Ogg data, Vorbis audio, stereo, 44100 Hz, ~91840 bps
./kurz/Podcasts/dh-20121015-kurz-018.ogg:    Ogg data, Vorbis audio, stereo, 44100 Hz, ~91840 bps

Xargs zur Rettung!

Das Umleiten der Ausgabe als Eingabe für einen anderen Befehl zu verwenden, ist viel einfacher, da das zweite Programm die Eingabe direkt verarbeitet. Xargs bietet also die schwierigere Variante zum Preis der einfacheren (Listing 6).

Listing 6

$ find Podcasts -name '*.ogg' | xargs file
Podcasts/dh-20130204-ausgabe-045.ogg: Ogg data, Vorbis audio, stereo, 44100 Hz, ~91840 bps
Podcasts/dh-20130107-ausgabe-044.ogg: Ogg data, Vorbis audio, stereo, 44100 Hz, ~91840 bps

Xargs hat hier die Ausgabe von Find als Eingabe gelesen, das als Parameter angegebene Programm aufgerufen und ihm die erhaltenen Dateinamen als Parameter mitgegeben. Dabei trennt es die auf der Standardeingabe übergebenen Zeichenketten ebenfalls an Leerzeichen einschließlich Zeilenumbrüchen auf (Listing 7).

Listing 7

$ find Musik -name '*.ogg' | xargs file
xargs: unmatched single quote; by default quotes are special to xargs unless you use the -0 option
Musik/Roxette: ERROR: cannot open `Musik/Roxette' (No such file or directory)
/dev/stdin:             empty
June:          ERROR: cannot open `June' (No such file or directory)
Afternoon.ogg: ERROR: cannot open `Afternoon.ogg' (No such file or directory)
Musik/Roxette: ERROR: cannot open `Musik/Roxette' (No such file or directory)
/dev/stdin:             empty
I:             ERROR: cannot open `I' (No such file or directory)

Auf den ersten Blick hat sich nichts verbessert. Der Vorteil von Xargs liegt aber darin, dass Sie mit der Kommandozeilenoption -d festlegen dürfen, an welchem Zeichen es trennt. In Listing 7 waren die Dateinamen mit Zeilenumbrüchen getrennt. Diese kommen nun als Trenner zum Einsatz (Listing 8).

Listing 8

$ find Musik -name '*.ogg' | xargs -d '\n' file
Musik/Roxette - June Afternoon.ogg:           Ogg data, Vorbis audio, [...]
Musik/Roxette - I Don't Want to Get Hurt.ogg: Ogg data, Vorbis audio, [...]
Musik/Roxette - Joyride.ogg:                  Ogg data, Vorbis audio, [...]
Musik/Roxette - Crash! Boom! Bang!.ogg:       Ogg data, Vorbis audio, [...]
Musik/Roxette - Almost Unreal.ogg:            Ogg data, Vorbis audio, [...]

Enthalten die Dateinamen einen Zeilenumbruch, verwenden Sie eines der beiden einzigen Zeichen als Trenner, die nie in einem Posix-konformen Dateinamen vorkommen dürfen: das Nullzeichen mit ASCII-Code 0. Weil dies ein so typischer Fall ist, haben die Entwickler sowohl Find als auch Xargs gleich passende Optionen spendiert (Listing 9).

Listing 9

$ find . -type f -print0 | xargs -0 file
./Datei
mit
Zeilenumbrüchen.txt: ASCII text

Die Option -print0 veranlasst Find, bei der Ausgabe jeden Dateinamen mit einem Nullzeichen abzuschließen; mittels -0 trennt Xargs die Eingabe nur an solchen. Es handelt sich bei den Zeichen in den Optionen jeweils um die Ziffer Null.

Xargs-Varianten

Xargs ist in praktisch jeder Linux- oder BSD-Distribution enthalten und auch Mac OS X hat Xargs mit an Bord. Unter Linux kommt fast immer die Implementation des GNU-Projekts zum Einsatz. Das Programm zählt dort zusammen mit Find und Locate zu den GNU Find Utilities [1].

Allerdings sind nicht alle Implementationen identisch. Sowohl die von FreeBSD [2] und NetBSD [3] (sie kommt auch unter Mac OS X [4] zum Einsatz) als auch die von GNU kennen die Option -0, obwohl diese nicht im Posix-Standard [5] vorkommt. Die Option -d findet sich dagegen nur in der Implementation des GNU-Projekts [6].

Diesen Artikel als PDF kaufen

Express-Kauf als PDF

Umfang: 5 Heftseiten

Preis € 0,99
(inkl. 19% MwSt.)

LinuxCommunity kaufen

Einzelne Ausgabe
 
Abonnements
 
TABLET & SMARTPHONE APPS
Bald erhältlich
Get it on Google Play

Deutschland

Ähnliche Artikel

Kommentare

Infos zur Publikation

LU 07/2017: VIDEOSCHNITT

Digitale Ausgabe: Preis € 0,00
(inkl. 19% MwSt.)

LinuxUser erscheint monatlich und kostet 5,95 Euro (mit DVD 8,50 Euro). Weitere Infos zum Heft finden Sie auf der Homepage.

Das Jahresabo kostet ab 86,70 Euro. Details dazu finden Sie im Computec-Shop. Im Probeabo erhalten Sie zudem drei Ausgaben zum reduzierten Preis.

Bei Google Play finden Sie digitale Ausgaben für Tablet & Smartphone.

HINWEIS ZU PAYPAL: Die Zahlung ist ohne eigenes Paypal-Konto ganz einfach per Kreditkarte oder Lastschrift möglich!

Aktuelle Fragen

Irgend ein Notebook mit Linux Mint - vllt der Dell Latitude 3480???
Universit Freiburg, 26.06.2017 13:51, 0 Antworten
Hey Leute, bin am Verzweifeln weil ich super gerne auf Linux umsteigen würde aber kein Noteboo...
scannen mit LINUXMINT 18.0 - Brother DCP - 195 C
Christoph-J. Walter, 21.06.2017 08:47, 4 Antworten
Seit LM 18.0 kann ich nicht mehr direkt scannen. Obwohl ich die notwendigen Tools von der Brothe...
Anfänger Frage
Klaus Müller, 24.05.2017 14:25, 2 Antworten
Hallo erstmal. Habe von linux nicht so viel erfahrung müsste aber mal ne doofe frage stellen. A...
Knoppix-Live-CD (8.0 LU-Edition) im Uefiboot?
Thomas Weiss, 26.04.2017 20:38, 4 Antworten
Hallo, Da mein Rechner unter Windows 8.1/64Bit ein Soundproblem hat und ich abklären wollte, o...
Grub2 reparieren
Brain Stuff, 26.04.2017 02:04, 7 Antworten
Ein Windows Update hat mir Grub zerschossen ... der Computer startet nicht mehr mit Grub, sondern...