403 Stimmen

Lassen Sie xargs Dateinamen verarbeiten, die Leerzeichen enthalten

$ ls *mp3 | xargs mplayer  

Wiedergabe von Lemon.  
Datei nicht gefunden: 'Lemon'  
Wiedergabe von Tree.mp3.  
Datei nicht gefunden: 'Tree.mp3'  

Beenden... (Dateiende)  

Mein Befehl schlägt fehl, weil die Datei "Lemon Tree.mp3" Leerzeichen enthält und xargs daher denkt, es handele sich um zwei Dateien. Kann ich Find + xargs mit solchen Dateinamen verwenden?

9voto

Bendel Punkte 91
find . -name 'Lemon*.mp3' -print0 | xargs -­0 -i mplayer '{}' 

Dies half mir in meinem Fall, verschiedene Dateien mit Leerzeichen zu löschen. Es sollte auch mit mplayer funktionieren. Der entscheidende Trick sind die Anführungszeichen. (Getestet unter Linux Xubuntu 14.04.)

7voto

shrewmouse Punkte 4278

Ich weiß, dass ich die Frage zu xargs nicht direkt beantworte, aber es lohnt sich, die Option -exec von find zu erwähnen.

Angenommen, das folgende Dateisystem:

[root@localhost bokeh]# tree --charset assci bands
bands
|-- Dream\ Theater
|-- King's\ X
|-- Megadeth
`-- Rush

0 directories, 4 files

Der find-Befehl kann so angepasst werden, dass er mit den Leerzeichen in Dream Theater und King's X umgeht. Also, um die Schlagzeuger jeder Band mit grep zu finden:

[root@localhost]# find bands/ -type f -exec grep Drums {} +
bands/Dream Theater:Drums:Mike Mangini
bands/Rush:Drums: Neil Peart
bands/King's X:Drums:Jerry Gaskill
bands/Megadeth:Drums:Dirk Verbeuren

In der -exec-Option steht {} für den Dateinamen inklusive Pfad. Beachten Sie, dass Sie es nicht escapen oder in Anführungszeichen setzen müssen.

Der Unterschied zwischen den Terminatoren von -exec (+ und ;) besteht darin, dass + so viele Dateinamen wie möglich zu einer Befehlszeile zusammenfasst. Während ; den Befehl für jeden Dateinamen ausführt.

Also wird find bands/ -type f -exec grep Drums {} + zu folgendem führen:

grep Drums "bands/Dream Theater" "bands/Rush" "bands/King's X" "bands/Megadeth"

und find bands/ -type f -exec grep Drums {} \; wird zu folgendem führen:

grep Drums "bands/Dream Theater"
grep Drums "bands/Rush"
grep Drums "bands/King's X"
grep Drums "bands/Megadeth"

Im Falle von grep hat dies den Nebeneffekt, entweder den Dateinamen auszudrucken oder nicht.

[root@localhost bokeh]# find bands/ -type f -exec grep Drums {} \;
Drums:Mike Mangini
Drums: Neil Peart
Drums:Jerry Gaskill
Drums:Dirk Verbeuren

[root@localhost bokeh]# find bands/ -type f -exec grep Drums {} +
bands/Dream Theater:Drums:Mike Mangini
bands/Rush:Drums: Neil Peart
bands/King's X:Drums:Jerry Gaskill
bands/Megadeth:Drums:Dirk Verbeuren

Natürlich kontrollieren grep's Optionen -h und -H, ob der Dateiname unabhängig davon gedruckt wird, wie grep aufgerufen wird.


xargs

xargs kann auch steuern, wie viele Dateien auf der Befehlszeile sind.

xargs gruppiert standardmäßig alle Argumente in eine Zeile. Um dasselbe zu erreichen, was -exec \; tut, verwenden Sie xargs -l. Beachten Sie, dass die Option -t xargs sagt, den Befehl vor der Ausführung zu drucken.

[root@localhost bokeh]# find ./bands -type f  | xargs -d '\n' -l -t grep Drums
grep Drums ./bands/Dream Theater 
Drums:Mike Mangini
grep Drums ./bands/Rush 
Drums: Neil Peart
grep Drums ./bands/King's X 
Drums:Jerry Gaskill
grep Drums ./bands/Megadeth 
Drums:Dirk Verbeuren

Beachten Sie, dass die Option -l xargs sagt, grep für jeden Dateinamen auszuführen.

Im Vergleich zum Standard (also keine -l-Option):

[root@localhost bokeh]# find ./bands -type f  | xargs -d '\n'  -t grep Drums
grep Drums ./bands/Dream Theater ./bands/Rush ./bands/King's X ./bands/Megadeth 
./bands/Dream Theater:Drums:Mike Mangini
./bands/Rush:Drums: Neil Peart
./bands/King's X:Drums:Jerry Gaskill
./bands/Megadeth:Drums:Dirk Verbeuren

xargs bietet eine bessere Kontrolle darüber, wie viele Dateien auf der Befehlszeile stehen können. Mit der Option -l geben Sie die maximale Anzahl von Dateien pro Befehl an.

[root@localhost bokeh]# find ./bands -type f  | xargs -d '\n'  -l2 -t grep Drums
grep Drums ./bands/Dream Theater ./bands/Rush 
./bands/Dream Theater:Drums:Mike Mangini
./bands/Rush:Drums: Neil Peart
grep Drums ./bands/King's X ./bands/Megadeth 
./bands/King's X:Drums:Jerry Gaskill
./bands/Megadeth:Drums:Dirk Verbeuren
[root@localhost bokeh]# 

Beachten Sie, dass grep mit zwei Dateinamen ausgeführt wurde, aufgrund von -l2.

5voto

Byron Formwalt Punkte 51

Auf macOS 10.12.x (Sierra) können Sie bei Dateinamen oder Unterverzeichnissen, die Leerzeichen enthalten, Folgendes verwenden:

find . -name '*.swift' -exec echo '"{}"' \; |xargs wc -l

4voto

Asclepius Punkte 48774

ls | grep mp3 | sed -n "7p" | xargs -i mplayer {}

Beachten Sie, dass in dem obigen Befehl xargs für jede Datei erneut mplayer aufruft. Dies kann für mplayer unerwünscht sein, aber für andere Ziele in Ordnung sein.

3voto

Jonathan Leffler Punkte 694013

Es hängt davon ab, (a) wie sehr Sie an der Nummer 7 im Vergleich zu Zitronen hängen und (b) ob einige Ihrer Dateinamen Zeilenumbrüche enthalten (und ob Sie bereit sind, sie umzubenennen, falls dies der Fall ist).

Es gibt viele Möglichkeiten, damit umzugehen, aber einige davon sind:

mplayer Lemon*.mp3

find . -name 'Lemon*.mp3' -exec mplayer {} ';'

i=0
for mp3 in *.mp3
do
    i=$((i+1))
    [ $i = 7 ] && mplayer "$mp3"
done

for mp3 in *.mp3
do
    case "$mp3" in
    (Lemon*) mplayer "$mp3";;
    esac
done

i=0
find . -name *.mp3 |
while read mp3
do
    i=$((i+1))
    [ $i = 7 ] && mplayer "$mp3"
done

Die read-Schleife funktioniert nicht, wenn Dateinamen Zeilenumbrüche enthalten; die anderen funktionieren auch richtig, selbst wenn Zeilenumbrüche in den Namen vorkommen (ganz zu schweigen von Leerzeichen). Meiner Meinung nach sollten Sie, wenn Dateinamen einen Zeilenumbruch enthalten, die Datei ohne den Zeilenumbruch umbenennen. Die Verwendung von doppelten Anführungszeichen um den Dateinamen herum ist entscheidend dafür, dass die Schleifen korrekt funktionieren.

Wenn Sie GNU find und GNU xargs (oder FreeBSD (*BSD?), oder Mac OS X) haben, können Sie auch die Optionen -print0 und -0 verwenden, wie folgt:

find . -name 'Lemon*.mp3' -print0 | xargs -0 mplayer

Dies funktioniert unabhängig vom Inhalt des Namens (die einzigen beiden Zeichen, die nicht in einem Dateinamen erscheinen können, sind der Schrägstrich und NUL, und der Schrägstrich verursacht keine Probleme in einem Dateipfad, daher deckt die Verwendung von NUL als Namens-Trennzeichen alles ab). Allerdings, wenn Sie die ersten 6 Einträge filtern müssen, benötigen Sie ein Programm, das "Zeilen" endet durch NUL anstelle von Zeilenumbruch... und ich bin mir nicht sicher, ob es das gibt.

Der erste ist bei weitem der einfachste für den spezifischen Fall, den Sie haben; jedoch könnte er sich nicht auf Ihre anderen Szenarien erstrecken, die Sie noch nicht aufgelistet haben.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X