Ricerca nel sito web

Come utilizzare il comando Xargs in Linux [spiegato con esempi]


xargs è uno dei comandi più potenti in Linux. In questo tutorial imparerai a utilizzare il comando xargs con alcuni esempi pratici e utili.

xargs è uno dei comandi più potenti in Linux. In questo tutorial, ti mostrerò come puoi xargs convertire l'input standard in comandi.

Cos'è il comando xargs?

Il comando xargs legge righe di testo dall'input standard o dall'output di un altro comando e le trasforma in comandi e li esegue.

Troverai spesso il comando xargs utilizzato con il comando find. Il comando find ti fornisce un elenco di nomi di file e il comando xargs ti consente di utilizzare quei nomi di file, uno per uno, come se fossero input nell'altro comando.

Poiché xargs funziona sul reindirizzamento, consiglio vivamente di rispolverare la tua conoscenza di stdin, stdout e reindirizzamento delle pipe in Linux.

Come usare il comando xargs?

Il comando xargs ha la seguente sintassi:

xargs [options] [command [initial-arguments]]

Ma probabilmente non lo userai in quel modo. Il suo potere sta nel combinare l'output di un comando con un altro. Vediamolo con un semplice esempio.

Nella mia directory attuale, ho alcuni file di testo e flowers.txt ha il nome di tutti questi file:

abhishek@linux-console:~/tutorial$ ls
flowers.txt  lily.txt  one_lotus.txt  rose.txt  three_lotus.txt  two_lotus.txt
abhishek@linux-console:~/tutorial$ cat flowers.txt 
lily.txt
one_lotus.txt
rose.txt
three_lotus.txt
two_lotus.txt

Ora il mio obiettivo è vedere la dimensione del file di tutti i file menzionati in flowers.txt. Il buon senso dice che potrei combinare il comando cat per visualizzare tutti i nomi dei file e quindi collegarlo al comando du per verificare la dimensione del file.

Ma se lo inserisco direttamente, non fornirà la dimensione di ciascuno dei file menzionati nel file flowers.txt.

abhishek@linux-console:~/tutorial$ du -h
52K	.
abhishek@linux-console:~/tutorial$ cat flowers.txt | du -h
52K	.

Perché? Innanzitutto, il comando du non accetta input standard. In secondo luogo, l'output del comando cat non rappresenta i singoli nomi di file. È come una parola separata da un carattere di nuova riga.

La magia del comando xargs è che prenderà questo e il testo separato da spazi vuoti o nuove righe e li convertirà in input individuali per il comando successivo.

abhishek@linux-console:~/tutorial$ cat flowers.txt | xargs du -h
4.0K	lily.txt
4.0K	one_lotus.txt
16K	rose.txt
4.0K	three_lotus.txt
16K	two_lotus.txt

Consideralo come equivalente a fornire quei nomi di file al comando du:

abhishek@linux-console:~/tutorial$ du -h lily.txt one_lotus.txt rose.txt three_lotus.txt two_lotus.txt 
4.0K	lily.txt
4.0K	one_lotus.txt
16K	rose.txt
4.0K	three_lotus.txt
16K	two_lotus.txt

Adesso ti rendi conto della potenza del comando xargs, vero?

xargs e find: fatti l'uno per l'altro

Lo troverai spesso utilizzato in combinazione con il "comando trova".

Il comando find cerca file e directory e restituisce i loro nomi. Grazie a xargs, puoi utilizzare il risultato del comando find per scopi specifici come rinominarli, spostarli, eliminarli e quant'altro.

Diciamo che vuoi ottenere tutti i file che terminano con .txt e contengono la parola rosso. Puoi combinare i comandi find e grep con l'aiuto di xargs:

abhishek@linux-console:~/tutorial$ find . -type f -name "*.txt" | xargs grep -l red
./three_lotus.txt
./two_lotus.txt
./rose.txt

La combinazione di comandi find exec funziona in modo simile. Ma concentriamoci qui sul comando xargs.

Gestire i nomi dei file con spazi

Se hai un file con spazio nel nome, causerà problemi. Diciamo che ho rinominato three_lotus.txt in “tre lotus.txt”. Ora, quando viene elaborato tramite xargs, viene visto come due file separati come tre e lotus.txt.

abhishek@linux-console:~/tutorial$ find . -type f -name "*.txt" | xargs grep -l red
./two_lotus.txt
grep: ./three: No such file or directory
grep: lotus.txt: No such file or directory
./rose.txt

In questi casi, dovresti utilizzare l'opzione -print0 del comando find. Separa le righe con caratteri ASCII null anziché con caratteri di nuova riga. Allo stesso modo, dovresti anche usare xargs con -0 per accettare i valori null ASCII.

abhishek@linux-console:~/tutorial$ find . -type f -print0 -name "*.txt" | xargs -0 grep -l red
./two_lotus.txt
./three lotus.txt
./rose.txt

Guarda quale comando viene eseguito

Se vuoi vedere quale comando viene eseguito con l'aiuto di xargs, puoi usare l'opzione -t. Stamperà il comando effettivo in esecuzione.

abhishek@linux-console:~/tutorial$ find . -type f -name "*.txt" | xargs -t touch
touch ./three_lotus.txt ./two_lotus.txt ./lily.txt ./rose.txt

Forza xargs a richiedere conferma prima di eseguire il comando

Alcune situazioni richiedono molta attenzione, come l'eliminazione di file. Sarà una buona idea vedere quale comando verrà eseguito e avere la possibilità di negare l'esecuzione.

È possibile utilizzare l'opzione -p di xargs per ottenere il prompt.

abhishek@linux-console:~/tutorial$ find . -type f -name "*.txt" | xargs -p rm
rm ./three_lotus.txt ./two_lotus.txt ./lily.txt ./rose.txt ?...n

Utilizzo del segnaposto con xargs per ottenere un maggiore controllo su di esso

Per impostazione predefinita, il comando xargs aggiunge lo standard input come argomento alla fine del comando. Ciò crea un problema quando è necessario utilizzarlo prima dell'ultimo argomento.

Ad esempio, se usi il comando sposta, avrai bisogno prima dell'origine e poi della destinazione. Se vuoi spostare i file trovati in una directory di destinazione, questo comando non funzionerà:

abhishek@linux-console:~/tutorial$ find . -type f -name "*.txt" | xargs -p mv new_dir
mv new_dir ./three_lotus.txt ./two_lotus.txt ./lily.txt ./rose.txt ?...y
mv: target './rose.txt' is not a directory

Qui è dove puoi utilizzare i segnaposto in xargs con l'opzione -Mi piace questo:

abhishek@linux-console:~/tutorial$ find . -type f -name "*.txt" | xargs -p -I {} mv {} new_dir
mv ./three_lotus.txt new_dir ?...n
mv ./two_lotus.txt new_dir ?...n
mv ./lily.txt new_dir ?...n
mv ./rose.txt new_dir ?...n

Pensalo come se xargs ottenesse tutti i nomi dei file dal comando find e mantienili in {}. Quindi va al comando mv e fornisce il contenuto di {}.

La differenza principale qui è che invece di inserire tutti i nomi di file nello stesso comando, li aggiunge uno per uno. Questo è il motivo per cui è stato chiamato il comando mv per ciascun argomento (come puoi vedere nell'esempio sopra).

Nota: ho utilizzato {} come segnaposto. Potresti usare la maggior parte delle altre lettere o caratteri come segnaposto. {} è una scommessa sicura ed è facile da capire e distinguere.

Esecuzione di più comandi con xargs

Puoi utilizzare i segnaposto per eseguire più comandi con xargs.

abhishek@linux-console:~/tutorial$ find . -type f -name "*.txt" | xargs -I {} sh -c 'ls -l {}; du -h {}' 
-rw-rw-r-- 1 abhishek abhishek 0 May 28 17:02 ./three_lotus.txt
0	./three_lotus.txt
-rw-rw-r-- 1 abhishek abhishek 0 May 28 17:02 ./two_lotus.txt
0	./two_lotus.txt
-rw-rw-r-- 1 abhishek abhishek 0 May 28 17:02 ./lily.txt
0	./lily.txt
-rw-rw-r-- 1 abhishek abhishek 0 May 28 17:02 ./rose.txt
0	./rose.txt

Tieni presente che il segnaposto non si estenderà al successivo reindirizzamento della pipe o ad altro comando. Questo è il motivo per cui ho usato il comando sh qui.

C'è sempre di più...

Ho utilizzato principalmente find con il comando xargs negli esempi qui perché è quello che vedrai di più. Ma ciò non significa che xargs possa essere utilizzato solo con il comando find. Un esempio pratico di comando xargs è quando si desidera interrompere tutti i contenitori docker in esecuzione:

docker ps -q | xargs docker stop

Come la maggior parte degli altri comandi Linux, ci sono molte più opzioni anche con xargs. Puoi sempre fare riferimento alla pagina man del comando xargs per ulteriori informazioni.

Penso che gli esempi di comandi xargs elencati qui siano sufficienti per darti una buona comprensione di questo fantastico comando.

Se avete domande o suggerimenti, fatemelo sapere nella sezione commenti.

Articoli correlati: