So che, dato l="a b c"
,
echo $l | xargs ls
i rendimenti
ls a b c
Quale costrutto produce
mycommand -f a -f b -f c
So che, dato l="a b c"
,
echo $l | xargs ls
i rendimenti
ls a b c
Quale costrutto produce
mycommand -f a -f b -f c
Risposte:
Un modo per farlo:
echo "a b c" | xargs printf -- '-f %s\n' | xargs mycommand
Ciò presuppone a
, b
e c
non contengono spazi vuoti, a capo, virgolette o backslash. :)
Con GNU findutil
puoi gestire il caso generale, ma è leggermente più complicato:
echo -n "a|b|c" | tr \| \\0 | xargs -0 printf -- '-f\0%s\0' | xargs -0 mycommand
È possibile sostituire il |
separatore con qualche altro personaggio, che non figura in a
, b
o c
.
Modifica: Come osserva @MichaelMol , con un elenco molto lungo di argomenti c'è il rischio di traboccare la lunghezza massima degli argomenti a cui è possibile passare mycommand
. Quando ciò accade, l'ultimo xargs
divide l'elenco e ne esegue un'altra copia mycommand
, e c'è il rischio che rimanga non terminato -f
. Se ti preoccupi di quella situazione, potresti sostituire l'ultimo xargs -0
sopra con qualcosa del genere:
... | xargs -x -0 mycommand
Questo non risolverà il problema, ma si interromperà mycommand
quando l'elenco degli argomenti diventa troppo lungo.
mycommand
. Puoi sempre aggiungere -x
l'ultimo xargs
.
xargs
affatto, e usare solo find
se può essere usata. Questa soluzione è pericolosa; dovresti almeno avvisare del caso di fallimento nella tua risposta.
find
sarebbe una soluzione generale migliore, in particolare quando gli argomenti iniziali non sono nomi di file. :)
-f
e con uno strumento di esempio ls
usato per l'illustrazione, @ non-un-utente ha a che fare con nomi di file. E dato find
offre l' -exec
argomento, che ti permette di costruire una riga di comando, va bene. (Finché mycommand
è consentito eseguire più di una volta. In caso contrario, abbiamo un altro problema con l'uso di xargs
qui ...)
Un modo migliore per affrontarlo (IMO) sarebbe:
in zsh
:
l=(a b c)
mycommand -f$^l
o usando l'array zipping in modo che l'argomento non sia associato all'opzione:
l=(a b c) o=(-f)
mycommand "${o:^^l}"
In questo modo, funziona ancora se l' l
array contiene elementi vuoti o elementi contenenti spazi o qualsiasi altro carattere problematico per xargs
. Esempio:
$ 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
e fish
non ha zippatura di array)
Con gusci di tipo Bourne vecchio stile come bash
, potresti sempre fare (permettendo comunque qualsiasi carattere negli elementi $@
dell'array):
set -- a b c
for i do set -- "$@" -f "$i"; shift; done
mycommand "$@"
for i; do args+=('-f' "$i");done;
mycommand "${args[@]}"
. IDK se questo è più veloce, ma l'aggiunta di 2 elementi a un array sembra che dovrebbe essere O (n), mentre il tuo set
loop probabilmente copia e analizza nuovamente l'elenco arg accumulato ogni volta (O (n ^ 2)).
ARG_MAX
e avere un-f
parametro separato dal suo parametro associato.