Come convogliare l'output del comando ad altri comandi?


83

Esempio:

ls | echonon stampa nulla (una linea vuota, in realtà). Mi aspetto che stampi un elenco di file.

ls | grep 'foo', d'altra parte, funziona come previsto (stampa i file con "pippo" nel loro nome).

Quello che faccio in queste situazioni è qualcosa di simile: ls | while read OUT; do echo $OUT; donema questo è piuttosto ingombrante.

Perché il piping funziona con alcuni comandi, ma non con altri? Come posso aggirare questo problema?


2
Cosa ti aspetti ls | echodi fare? perché non semplicemente correre ls?
theomega,

12
Ho usato l'esempio più semplice che illustra il mio punto. In realtà ho riscontrato questo problema quando stavo cercando di creare un one-liner che mostrasse gli oggetti git nell'archivio oggetti e il loro tipo. Quindi, ho reindirizzato gli ID oggetto a git cat-file, ma semplicemente non ha funzionato. Apparentemente, l'eco ha lo stesso comportamento, quindi l'ho usato come esempio.
Mihai Rotaru,

guarda anche il comando -n per xargs, dice quanti argomenti mettere sul sottocomando. `... | xargs -n1 git cat-file`
Rich Homolka,

Risposte:


118

Esiste una distinzione tra argomenti della riga di comando e input standard. Una pipe collegherà l'output standard di un processo all'input standard di un altro. Così

ls | echo

Collega l'output standard di ls all'input standard di eco. Va bene vero? Bene, l'eco ignora l'input standard e scaricherà i suoi argomenti della riga di comando - che non sono nessuno in questo caso - il proprio stdout. L'output: niente di niente.

Ci sono alcune soluzioni in questo caso. Uno è usare un comando che legge stdin e dump su stdout, come cat.

ls | cat

Funzionerà, a seconda di quale sia la tua definizione di lavoro.

Ma per quanto riguarda il caso generale. Quello che vuoi davvero è convertire lo stdout di un comando in un argomento della riga di comando di un altro. Come altri hanno già detto, xargsin questo caso è lo strumento di supporto canonico, leggere la sua riga di comando richiede un comando dal suo stdin e costruire comandi da eseguire.

ls | xargs echo

Puoi anche convertirlo un po ', usando il comando di sostituzione $()

echo $(ls)

Farebbe anche quello che vuoi.

Entrambi questi strumenti sono piuttosto fondamentali per lo scripting della shell, dovresti imparare entrambi.

Per completezza, come indicato nella domanda, l'altro modo di base per convertire stdin in args da riga di comando è il readcomando incorporato della shell . Converte "parole" (parole definite dalla IFSvariabile) in una variabile temporanea, che è possibile utilizzare in qualsiasi esecuzione di comandi.


1
Una risposta molto utile e istruttiva, grazie! Attualmente sto imparando bash e ho visto sia xargs che la notazione $ (*) prima, ma non ho prestato molta attenzione a loro. Ora so quanto siano importanti e sicuramente li esaminerò.
Mihai Rotaru,

1
xargs potrebbe essere stato ciò che OP stava cercando.
Iktys,

19

ls | echostampa solo una riga vuota perché echonon legge alcun input; l'ultimo comando della pipeline è in realtà echoche non stampa nient'altro che una linea vuota.

Generalmente:

a | b

fa in modo che l'output di adiventi l'input di b. Ti consiglio di leggere la Pipelinessezione di man bash.


Se vuoi davvero usarlo lse echoinsieme ecco alcuni esempi (piuttosto inutili):

ls | xargs -L 1 echo
echo `ls`
for i in `ls` ; do echo $i ; done

11

Se vuoi echoil lscomando prova:

ls | xargs echo

Questo chiamerà echocon l'output di ls.


3
O ls | xargs -I {} echo {}se vuoi che venga chiamato per ogni linea individualmente
Alex Abdugafarov,

3

Perché non usare semplicemente:

echo `ls`

O molto più sicuro:

echo "`ls -lrt`"

4
O anche solo echo *.
Kazark,
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.