xargs è particolarmente utile quando hai un elenco di percorsi di file su stdin e vuoi fare qualcosa con loro. Per esempio:
$ git ls-files "*.tex" | xargs -n 1 sed -i "s/color/colour/g"
Esaminiamo questo passo per passo:
$ git ls-files "*.tex"
tex/ch1/intro.tex
tex/ch1/motivation.tex
....
In altre parole, il nostro input è un elenco di percorsi a cui vogliamo fare qualcosa.
Per scoprire cosa fa xargs con questi percorsi, un bel trucco è aggiungere echo
prima del tuo comando, in questo modo:
$ git ls-files "*.tex" | xargs -n 1 echo sed -i "s/color/colour/g"
sed -i "s/color/colour/g" tex/ch1/intro.tex
sed -i "s/color/colour/g" tex/ch1/motivation.tex
....
L' -n 1
argomento farà sì che xargs trasformi ogni riga in un comando a sé stante. Il sed -i "s/color/colour/g"
comando sostituirà tutte le occorrenze di color
con colour
per il file specificato.
Nota che funziona solo se non hai spazi nei tuoi percorsi. In tal caso, è necessario utilizzare percorsi con terminazione null come input per xargs passando il -0
flag. Un esempio di utilizzo sarebbe:
$ git ls-files -z "*.tex" | xargs -0 -n 1 sed -i "s/color/colour/g"
Che fa lo stesso di quello che abbiamo descritto sopra, ma funziona anche se uno dei percorsi contiene uno spazio.
Funziona con qualsiasi comando che produce nomi di file come output come find
o locate
. Se ti capita di usarlo in un repository git con molti file, potrebbe essere più efficiente usarlo git grep -l
invece di git ls-files
, in questo modo:
$ git grep -l "color" "*.tex" | xargs -n 1 sed -i "s/color/colour/g"
Il git grep -l "color" "*.tex"
comando fornirà un elenco di file "* .tex" contenente la frase "color".
xargs
e$(...)
), xargs è molto più sicuro della sostituzione dei comandi. E non ricordo di essermi mai imbattuto in un nome di file legittimo con una nuova riga al suo interno. I problemi di fuga e di espansione delle parole non riguardano la sostituzione dei comandi, non gli xargs?