Comandi: xargs
xargs
è uno dei filtri più utili che la command line offra perché consente di utilizzare un qualsiasi input come argomento di un comando.
Il caso tipico in cui si utilizza è quello in cui si vuole applicare un certo comando ad una lista di file selezionati, la cui selezione però non dipende dal nome, altrimenti sarebbe ovviamente più comodo usare i wildcards. Ad esempio supponiamo di voler verificare il tipo di tutti i file di una certa directory che contengono la parola "soft":
$ ls
file.csv newfile.csv testo1.txt testo2.txt
$ grep -l soft * | xargs file
file.csv: ASCII text
newfile.csv: ASCII text
testo1.txt: UTF-8 Unicode text
In pratica abbiamo costruito con grep -l
l'elenco dei file che contengono la parola soft, e poi con xargs
abbiamo impartito il comando file
. In pratica è come se avessimo dato:
$ file file.csv newfile.csv testo1.txt
Possiamo verificarlo velocemente grazie all'opzione -t che scrive nello stderr il comando prima di eseguirlo:
$ grep -l soft * | xargs -t file
file file.csv newfile.csv testo1.txt
file.csv: ASCII text
newfile.csv: ASCII text
testo1.txt: UTF-8 Unicode text
Ci sono casi in cui non vogliamo creare una sola riga di comando con tutti i file, ma vogliamo invece generare un comando singolo per ogni file.
xargs
lo può fare usando lo switch -l. Ad esempio:
$ grep -l soft * | xargs -t -l file
file file.csv
file.csv: ASCII text
file newfile.csv
newfile.csv: ASCII text
file testo1.txt
testo1.txt: UTF-8 Unicode text
Come possiamo vedere grazie allo switch -t, per l'effetto del parametro -l questa volta xargs
ha generato un singolo comando per ogni file.
Un altro uso tipico di xargs
è in coppia col comando find
. Vediamo ad esempio come eseguire una ricerca di una particolare parola in qualsiasi file con estensione .txt in un albero di sottodirectory:
$ find ./ -type f -name '*.txt' | xargs -d '\n' grep -l acquisizione
./Scrivania/Meeting.txt
./Scrivania/regole ferengi.txt
In questo caso abbiamo utilizzato find
per selezionare tutti i file di testo nelle sottodirectories, e poi con xargs
li abbiamo passati a grep
per eseguire la ricerca. Il parametro -d '\n' serve per fare in modo che i nomi di file contenenti spazi siano trattati correttamente, altrimenti xargs
separerebbe un nome come "il mio file.txt" in 3 pezzi: "il", "mio" e "file.txt".
Un altro esempio tipico è quello di uso insieme ad awk
per copiare o rinominare tutti i file con una certa estensione:
$ ls *.txt | awk '{print $1,$1".old"}' | xargs -t -l cp
cp testo1.txt testo1.txt.old
cp testo2.txt testo2.txt.old
$ ls
file.csv newfile.csv testo1.txt testo1.txt.old testo2.txt testo2.txt.old
Il comando xargs
ha moltissime opzioni e vi invito a esplorarne il manuale (man xargs
) per guardarle tutte e conoscere le infinite possibilità che offre.
switch -1
In realtà intendevo che lo switch -t, eseguendo l'output del comando, ci fa vedere che esegue una riga alla volta, ma in effetti la frase era poco chiara. L'ho corretta. Grazie!