Come utilizzare il comando xargs su Linux

Foto dell'autore

By kair

Hai la necessità di combinare diversi comandi Linux, ma uno di essi non gestisce l’input tramite pipe? xargs si rivela uno strumento prezioso, capace di acquisire l’output di un comando e trasmetterlo come argomenti a un altro.

Tutte le utility standard di Linux sono associate a tre flussi di dati: il flusso di input standard (stdin), il flusso di output standard (stdout) e il flusso di errore standard (stderr).

Questi flussi gestiscono dati testuali. L’input (stdin) viene fornito a un comando tramite testo, e la risposta (stdout) appare nella finestra del terminale come testo. Anche i messaggi di errore (stderr) vengono visualizzati come testo.

Una delle caratteristiche distintive dei sistemi operativi Linux e Unix è la possibilità di indirizzare l’output stdout di un comando all’input stdin di un altro. Il primo comando non si preoccupa se l’output non va alla finestra del terminale, e il secondo non si cura che l’input non provenga dalla tastiera.

Nonostante tutti i comandi Linux abbiano i tre flussi standard, non tutti accettano l’stdout di un altro comando come input per il loro stdin, limitando le possibilità di invio dati.

xargs, creato appositamente per costruire pipeline di esecuzione, permette a comandi come echo, rm e mkdir di accettare l’input standard come argomenti.

Il Funzionamento di xargs

xargs può accettare input da una pipe o da un file, e utilizza questo input come parametri per i comandi specificati. In assenza di un comando specifico, xargs usa echo come default.

Vediamo come xargs produce sempre una singola riga di output, anche con input su più righe.

L’opzione -1 di ls (un file per riga) genera una colonna di nomi di file.

ls -1 ./*.sh

Questo comando mostra i file di script nella directory corrente.

L’output è una singola colonna. Cosa accade se lo inviamo a xargs?

ls -1 ./*.sh | xargs

L’output viene visualizzato come un unico flusso di testo.

Questa capacità permette a xargs di inserire parametri in altri comandi.

xargs e il conteggio con wc

Possiamo usare xargs per permettere a wc di contare parole, caratteri e linee in più file.

ls *.page | xargs wc

Ecco cosa accade:

ls elenca i file *.page e li invia a xargs.
xargs passa i nomi a wc.
wc riceve i nomi come parametri della riga di comando.

Le statistiche di ogni file e il totale complessivo vengono visualizzati.

Conferma Interattiva con xargs

L’opzione -p (interattiva) fa sì che xargs richieda la conferma prima di procedere.

Inviando nomi di file a touch tramite xargs, touch crea i file.

echo 'one two three' | xargs -p touch

xargs mostra il comando e aspetta una risposta (‘y’ o ‘Y’ per confermare, ‘n’ o ‘N’ per negare, o semplicemente Invio, che equivale a ‘n’).

Il comando si esegue solo se si digita ‘y’ o ‘Y’.

Dopo aver premuto ‘y’ e Invio, controlliamo con ls che i file siano stati creati.

ls one two three

Esecuzione di Comandi Multipli con xargs

L’opzione -I (argomenti iniziali) permette di usare più comandi con xargs.

Questa opzione definisce una “stringa di sostituzione”. Ogni occorrenza del token per la stringa di sostituzione viene rimpiazzata dai valori forniti a xargs.

Il comando tree mostra le sottodirectory della directory corrente. L’opzione -d (directory) fa in modo che tree ignori i file.

tree -d

L’unica sottodirectory è “immagini”.

In un file “directories.txt” ci sono nomi di directory che vorremmo creare. Visualizziamo il contenuto con cat.

cat directories.txt

Usiamo questo file come input per xargs. Il comando da eseguire è:

cat directories.txt | xargs -I % sh -c 'echo %; mkdir %'

Analisi del comando:

cat directories.txt |: l’output del file (i nomi delle nuove directory) viene inviato a xargs.
xargs -I%: definisce il token “%” come “stringa di sostituzione”.
sh -c: avvia una nuova subshell. -c dice alla shell di leggere i comandi dalla riga di comando.
‘echo %; mkdir %’: ogni “%” viene sostituito dai nomi delle directory. echo mostra il nome, e mkdir la crea.

Le directory vengono elencate una alla volta.

Verifichiamo la creazione delle directory con tree.

tree -d

Copia di File in Multipli Percorsi

xargs permette di copiare file in più posizioni con un singolo comando.

Invieremo i nomi di due directory a xargs. xargs passerà solo un parametro alla volta al comando (cp). L’opzione -n (numero massimo) permette questo comportamento, impostandolo a uno.

L’opzione -v (verbose) di cp fornisce informazioni dettagliate.

echo ~/Backups/ ~/Documents/page-files/ | xargs -n 1 cp -v ./*.page

I file vengono copiati nelle due directory una alla volta, con cp che notifica ogni azione.

Eliminazione di File in Directory Nidificate

Se i nomi dei file hanno spazi o caratteri speciali, xargs potrebbe avere problemi. L’opzione -0 (null terminator) fa usare a xargs il carattere null come delimitatore per i nomi.

find ha l’opzione -print0 (nome completo, carattere nullo) per gestire spazi e caratteri strani.

find . -name "*.png" -type f -print0 | xargs -0 rm -v -rf "{}"

Analisi del comando:

find . -name “*.png”: find cerca dalla directory corrente (“.”) oggetti con nomi che corrispondono a “*.png” e che sono file (-type f).
-print0: i nomi vengono terminati da un carattere null, gestendo spazi e caratteri strani.
xargs -0: xargs considera i nomi di file con terminazione null, gestendo spazi e caratteri strani.
rm -v -rf “{}”: rm è dettagliato (-v), ricorsivo (-r), rimuove i file senza chiedere (-f). “{}” è sostituito da ogni nome di file.

La ricerca viene eseguita in tutte le sottodirectory, ed i file che corrispondono vengono eliminati.

Rimozione di Directory Nidificate

Rimuoviamo un gruppo di sottodirectory. tree mostra la loro struttura.

tree -d

find . -name "level_one" -type d print0 | xargs -0 rm -v -rf "{}"

Questo comando utilizza find per cercare nella directory corrente le directory “level_one”. I nomi delle directory vengono passati a rm tramite xargs.

La differenza principale rispetto al comando precedente è che cerchiamo directory con -type d.

Ogni directory rimossa viene mostrata. Verifichiamo con tree:

tree -d

Tutte le sottodirectory nidificate sono state eliminate.

Eliminare Tutti i File Tranne uno Specifico Tipo

Usiamo find, xargs e rm per eliminare tutti i file eccetto uno specifico tipo. Con l’opzione -not, find restituisce i nomi che *non* corrispondono al modello. Usiamo di nuovo -I, con il token di sostituzione “{}”.

find . -type f -not -name "*.sh" -print0 | xargs -0 -I {} rm -v {}

Verifichiamo con ls. Rimangono solo i file “*.sh”.

ls -l

Creare Archivi con Xargs

find può cercare file e passarli a tar tramite xargs, per creare archivi. Cerchiamo i file “*.page” nella directory corrente.

find ./ -name "*.page" -type f -print0 | xargs -0 tar -cvzf page_files.tar.gz

I file vengono elencati durante la creazione dell’archivio.

Il Mediatore di Dati

xargs è un ponte tra i comandi che producono informazioni e quelli che non sono progettati per riceverle.

Sia xargs che find hanno numerose opzioni. Si consiglia di consultare le loro pagine man per approfondimenti.