Ich weiß, dass gegeben l="a b c"
,
echo $l | xargs ls
Ausbeuten
ls a b c
Welches Konstrukt ergibt
mycommand -f a -f b -f c
Ich weiß, dass gegeben l="a b c"
,
echo $l | xargs ls
Ausbeuten
ls a b c
Welches Konstrukt ergibt
mycommand -f a -f b -f c
Antworten:
Ein Weg, es zu tun:
echo "a b c" | xargs printf -- '-f %s\n' | xargs mycommand
Dies setzt voraus a
, b
und c
enthält keine Leerzeichen, Zeilenumbrüche, Anführungszeichen oder Backslashes. :)
Mit GNU können findutil
Sie den allgemeinen Fall behandeln, aber es ist etwas komplizierter:
echo -n "a|b|c" | tr \| \\0 | xargs -0 printf -- '-f\0%s\0' | xargs -0 mycommand
Sie können den ersetzen |
Separator mit einem anderen Zeichen, dass nicht angezeigt wird in a
, b
oder c
.
Bearbeiten: Wie @MichaelMol feststellt, besteht bei einer sehr langen Liste von Argumenten die Gefahr, dass die maximale Länge der Argumente, an die übergeben werden kann, überschritten wird mycommand
. In diesem Fall xargs
wird die Liste beim letzten Mal geteilt und eine weitere Kopie von ausgeführt mycommand
. Es besteht die Gefahr, dass die Liste nicht abgeschlossen wird -f
. Wenn Sie sich wegen dieser Situation Sorgen machen, können Sie die letzte xargs -0
durch Folgendes ersetzen :
... | xargs -x -0 mycommand
Dies wird das Problem nicht lösen, aber die Ausführung wird abgebrochen, mycommand
wenn die Liste der Argumente zu lang wird.
mycommand
. Sie könnten immer -x
zum letzten hinzufügen xargs
.
xargs
und nur zu verwenden, find
wenn es verwendet werden kann. Diese Lösung ist gefährlich; Sie sollten in Ihrer Antwort zumindest vor dem Fehlerfall warnen.
find
bessere allgemeine Lösung, insbesondere wenn die anfänglichen Argumente keine Dateinamen sind. :)
-f
und einem Beispieltool ls
zur Veranschaulichung mit Dateinamen befasst. Und da find
bietet das -exec
Argument, das Ihnen erlaubt zu konstruieren eine Befehlszeile, es ist in Ordnung. (Solange mycommand
erlaubt ist, mehr als einmal auszuführen. Wenn es nicht ist, dann haben wir ein anderes Problem mit der Verwendung von xargs
hier ...)
Ein besserer Weg, um es anzugehen (IMO) wäre:
in zsh
:
l=(a b c)
mycommand -f$^l
oder mit Array-Zipping, damit das Argument nicht an die Option angehängt wird:
l=(a b c) o=(-f)
mycommand "${o:^^l}"
Auf diese Weise funktioniert es immer noch, wenn das l
Array leere Elemente oder Elemente enthält, die Leerzeichen oder andere problematische Zeichen für enthalten xargs
. Beispiel:
$ l=(a '' '"' 'x y' c) o=(-f)
$ printf '<%s>\n' "${o:^^l}"
<-f>
<a>
<-f>
<>
<-f>
<">
<-f>
<x y>
<-f>
<c>
in rc
:
l=(a b c)
mycommand -f$l
in fish
:
set l a b c
mycommand -f$l
(AFAIK rc
und fish
kein Array-Zippen)
Mit Bourne-ähnlichen Shells im alten Stil bash
könnten Sie immer Folgendes tun (und trotzdem jedes Zeichen in den Elementen des $@
Arrays zulassen):
set -- a b c
for i do set -- "$@" -f "$i"; shift; done
mycommand "$@"
for i; do args+=('-f' "$i");done;
mycommand "${args[@]}"
. IDK, wenn dies schneller ist, aber das Anhängen von 2 Elementen an ein Array wie O (n) erscheint, während Ihre set
Schleife wahrscheinlich jedes Mal die akkumulierte Arg-Liste kopiert und erneut analysiert (O (n ^ 2)).
ARG_MAX
, einen-f
von seinem gepaarten Parameter getrennten Wert zu überschreiten und zu haben .