Comandi: xargs

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.

Tommaso
Piccola correzione
Written by Tommaso on 16 Dicembre 2020

switch -1

Maurizio Admin
Written by Maurizio on 14 Marzo 2021

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!