Perché è necessario xargs?


25

Supponiamo di voler rimuovere tutti i file in una directory tranne uno chiamato "notes.txt". Vorrei farlo con il gasdotto, ls | grep -v "notes.txt" | xargs rm. Perché ho bisogno di xargs se l'output del secondo pipe è l'input che rm dovrebbe usare?

Per motivi di confronto, la pipeline echo "#include <knowledge.h>" | cat > foo.cinserisce il testo echo nel file senza l'uso di xargs. Qual è la differenza tra queste due condutture?


3
Non utilizzare ls | grep -v "notes.txt" | xargs rmper rimuovere tutto tranne notes.txt, o in generale, non analizzare mai l' lsoutput . Il tuo comando verrebbe interrotto se un singolo file contenesse uno spazio, ad esempio. Il modo più sicuro sarebbe rm !(notes.txt)in Bash (con shopt -s extglobset), o rm ^notes.txtin Zsh (con EXTENDED_GLOB) ecc.
Slhck,

Per evitare spazi che potresti fare find . -maxdepth 1 -mindepth 1 -print0 | xargs -0invece di ls | xargs:-)
flob il

Risposte:


35

Stai confondendo due tipi molto diversi di input: STDIN e argomenti. Gli argomenti sono un elenco di stringhe fornite al comando all'avvio, in genere specificandole dopo il nome del comando (ad es. echo these are some argumentsO rm file1 file2). STDIN, d'altra parte, è un flusso di byte (a volte testo, a volte no) che il comando può (facoltativamente) leggere dopo l'avvio. Ecco alcuni esempi (nota che catpuò prendere argomenti o STDIN, ma fa cose diverse con loro):

echo file1 file2 | cat    # Prints "file1 file2", since that's the stream of
                          # bytes that echo passed to cat's STDIN
cat file1 file2    # Prints the CONTENTS of file1 and file2
echo file1 file2 | rm    # Prints an error message, since rm expects arguments
                         # and doesn't read from STDIN

xargs può essere pensato come convertire input in stile STDIN in argomenti:

echo file1 file2 | cat    # Prints "file1 file2"
echo file1 file2 | xargs cat    # Prints the CONTENTS of file1 and file2

echo in realtà fa più o meno il contrario: converte i suoi argomenti in STDOUT (che può essere reindirizzato a STDIN di altri comandi):

echo file1 file2 | echo    # Prints a blank line, since echo doesn't read from STDIN
echo file1 file2 | xargs echo    # Prints "file1 file2" -- the first echo turns
                                 # them from arguments into STDOUT, xargs turns
                                 # them back into arguments, and the second echo
                                 # turns them back into STDOUT
echo file1 file2 | xargs echo | xargs echo | xargs echo | xargs echo    # Similar,
                                 # except that it converts back and forth between
                                 # args and STDOUT several times before finally
                                 # printing "file1 file2" to STDOUT.

9

cataccetta input da STDINe rmnon. Per tali comandi è necessario xargsscorrere le STDINrighe riga per riga ed eseguire i comandi con i parametri della riga comandi.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.