Comando xargs in Linux: passare argomenti e gestire i nomi di file

xargs legge elementi dallo standard input e li passa come argomenti a un altro comando. Serve, per esempio, a trasformare un elenco di nomi di file in chiamate a wc: una normale pipe, invece, trasmette dati allo standard input del comando successivo.

Per nomi di file arbitrari, usate find -print0 insieme a xargs -0. Il separatore NUL mantiene intatti spazi, virgolette e ritorni a capo presenti nei nomi; il formato predefinito di xargs interpreta invece spazi, tabulazioni, nuove righe, virgolette e barre inverse.

Sintassi e passaggio degli argomenti

comando-generatore | xargs [opzioni] comando-da-eseguire [argomenti-fissi...]

Gli argomenti fissi precedono quelli ricavati dall’input. xargs può avviare il comando più volte, suddividendo gli elementi in gruppi compatibili con i limiti di lunghezza della riga di comando del sistema. Non avvia implicitamente una shell: operatori come | o > contenuti nei dati non diventano automaticamente una pipeline o una redirezione.

Con GNU xargs, il comando avviato legge normalmente lo standard input da /dev/null. Non aspettatevi quindi che riceva anche il flusso originale come dati: l’uso principale qui è costruire argomenti. Verificate implementazione e opzioni con xargs --version sui sistemi GNU e con man xargs sul sistema effettivamente usato.

Esempio completo con nomi contenenti spazi

Eseguite tutto il blocco seguente in Bash. Crea i file necessari in una nuova directory temporanea, all’interno di una subshell: la directory di lavoro della shell chiamante non cambia e i file già presenti non vengono sovrascritti. L’ultima riga mostra dove sono rimasti i dati della prova; ispezionateli e rimuovete soltanto quella directory quando non serve più.

(
set -eu
labdir=$(mktemp -d)
cd "$labdir"
mkdir reports
printf 'first\nsecond\n' > 'reports/two words.txt'
printf 'third\n' > 'reports/plain.txt'
printf '%s\0' 'reports/two words.txt' 'reports/plain.txt' |
    xargs -0 -r -n 1 printf 'ARG=[%s]\n'
find reports -type f -name '*.txt' -print0 | xargs -0 -r wc -l
printf 'two words\n' | xargs -n 1 printf 'SPLIT=[%s]\n'
printf 'Lab files: %s\n' "$labdir"
)

Le due righe con ARG= mostrano rispettivamente reports/two words.txt e reports/plain.txt come argomenti interi. Il nome contenente uno spazio non viene diviso. wc -l conta 2 righe nel primo file e 1 nel secondo, per un totale di 3; l’ordine delle righe relative ai file può dipendere dall’attraversamento di find.

L’ultima pipeline produce SPLIT=[two] e SPLIT=[words] su due righe: senza -0, lo spazio separa due elementi. La prova usa printf per rendere visibili i confini degli argomenti, prima di sostituirlo eventualmente con un comando che modifica file.

Opzioni principali: delimitatori, gruppi e sostituzione

Opzione Comportamento e condizioni
-0 Legge elementi separati da NUL. Virgolette e barre inverse sono caratteri letterali; il produttore deve emettere lo stesso separatore.
-r Non avvia il comando se l’input non contiene elementi. È disponibile in GNU xargs ed è inclusa in POSIX.1-2024; controllate i sistemi più vecchi.
-n N Passa al massimo N elementi dell’input a ogni esecuzione. I limiti di lunghezza possono imporre gruppi più piccoli; gli argomenti fissi non fanno parte di N.
-P N In GNU xargs, avvia al massimo N processi contemporaneamente. Il valore predefinito è 1; scegliete un limite esplicito e verificate la disponibilità su altre implementazioni.
-I segnaposto Inserisce ogni elemento nei punti degli argomenti iniziali che contengono il segnaposto. Senza -0, l’input è organizzato per righe, con regole proprie per virgolette e barre inverse.

In GNU xargs, senza -r un input vuoto provoca comunque un’esecuzione del comando, con i soli argomenti iniziali. Un elemento vuoto delimitato da NUL è invece un argomento presente: non equivale a un flusso senza elementi. Anche -0 è stata aggiunta a POSIX.1-2024; non va descritta come un’opzione esclusivamente GNU, pur dovendo controllare i sistemi che seguono specifiche precedenti.

-I serve quando il dato deve occupare una posizione precisa, per esempio printf '%s\0' 'due parole' | xargs -0 -I '{}' printf 'ARG=[%s]\n' '{}'. Qui NUL conserva il testo come un solo elemento. Il solo -I non sostituisce -0 per nomi arbitrari: una nuova riga nel nome resta problematica e virgolette e barre inverse hanno un significato speciale. Evitate di combinare -I e -n: in GNU le opzioni di raggruppamento possono prevalere l’una sull’altra e produrre avvisi.

Nomi di file e operazioni che modificano dati

Una costruzione come find ... -print | xargs rm può dividere erroneamente nomi contenenti spazi o nuove righe. Non eseguitela come prova. Per trasferire nomi arbitrari, mantenete NUL da un capo all’altro con -print0 e -0, oppure valutate find -exec, che passa direttamente i nomi come argomenti senza serializzarli in un elenco testuale.

Controllate prima la selezione e gli argomenti usando un comando innocuo, come nel laboratorio. Il separatore corretto non impedisce che un nome iniziante con - sia interpretato come un’opzione dal comando destinatario: usate percorsi con un prefisso come ./ oppure il suo separatore --, quando supportato, nella posizione prevista da quel comando.

NUL non elimina inoltre le condizioni di concorrenza: tra la ricerca di un percorso e l’operazione sul file, un altro processo potrebbe modificarlo o sostituirlo. Anche una selezione corretta richiede quindi attenzione a directory condivise, permessi e conseguenze dell’operazione; non considerate -0 una garanzia contro modifiche simultanee del filesystem.

Parallelismo ed errori di esecuzione

Con GNU xargs, -P 2 -n 1 consente fino a due processi, ciascuno con un elemento dell’input. Senza un criterio di suddivisione, tutto l’input potrebbe entrare in una sola chiamata e il parallelismo non porterebbe vantaggi. Evitate -P 0 come scelta predefinita: in GNU significa non imporre un limite al numero di processi avviabili.

L’ordine di completamento e dell’output può cambiare; più processi che scrivono nello stesso file o modificano la stessa risorsa possono interferire. Usate il parallelismo solo se le operazioni sono indipendenti e il limite scelto rispetta memoria, CPU e capacità del servizio coinvolto.

Controllate anche lo stato finale, subito dopo la pipeline, con printf '%s\n' "$?". In GNU xargs, 0 indica successo; 123 segnala che almeno un comando è terminato normalmente con uno stato diverso da 0 e 255; 124 indica che un comando è terminato con 255; 127 indica che il comando non è stato trovato. Un errore non annulla le chiamate già eseguite: prima di riprovare, verificate quali risultati esistono già.

Domanda frequente

Qual è la differenza tra una pipe e xargs?

comando1 | comando2 invia dati allo standard input di comando2. comando1 | xargs comando2 fa interpretare a xargs quegli elementi e avvia comando2 con gli elementi come argomenti, eventualmente in più chiamate. Scegliete in base a ciò che il comando destinatario accetta: un flusso di dati oppure una lista di argomenti.

Documentazione ufficiale e portabilità

La pagina di manuale di GNU xargs descrive le opzioni GNU, gli stati di uscita e i limiti di sicurezza. La specifica POSIX.1-2024 di xargs definisce il comportamento standard, comprese le aggiunte -0 e -r. Per un sistema meno recente, confrontate sempre queste indicazioni con il manuale installato.