2010-09-16 13:40:08 +0000 2010-09-16 13:40:08 +0000
88
88

Come convogliare l'output dei comandi verso altri comandi?

Esempio:

ls | echo non stampa nulla (una linea bianca, in realtà). Mi aspetterei che stampasse una lista di file.

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

Quello che faccio in queste situazioni è qualcosa come: ls | while read OUT; do echo $OUT; done ma questo è piuttosto ingombrante.

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

Risposte (4)

123
123
123
2010-09-16 14:16:59 +0000

C'è una distinzione tra gli argomenti della linea di comando e lo standard input. Una pipe collega lo standard output di un processo allo standard input di un altro. Quindi

ls | echo

collega lo standard output di ls allo standard input di echo. Va bene, vero? Bene, echo ignora lo standard input e scaricherà i suoi argomenti della linea di comando - che in questo caso non sono nessuno - sul proprio stdout. L'output: niente di niente.

Ci sono alcune soluzioni in questo caso. Una è quella di usare un comando che legga stdin e scarichi su stdout, come cat.

ls | cat

Funzionerà, a seconda della vostra definizione di lavoro.

Ma che dire del caso generale. Quello che volete veramente è convertire lo stdout di un comando in args della linea di comando di un altro. Come altri hanno detto, xargs è il canonico strumento di aiuto in questo caso, leggendo gli argomenti della linea di comando di un comando dal suo stdin, e costruendo i comandi da eseguire.

ls | xargs echo

Potresti anche convertire questo un po’, usando il comando di sostituzione $()

echo $(ls)

farebbe anche quello che vuoi.

Entrambi questi strumenti sono piuttosto fondamentali per lo scripting di shell, dovresti impararli entrambi.

Per completezza, come indicate nella domanda, l'altro modo di base per convertire stdin in args della linea di comando è il comando integrato della shell read. Esso converte le “parole” (parole come definite dalla variabile IFS) in una variabile temporanea, che potete usare in qualsiasi esecuzione di comando.

19
19
19
2010-09-16 13:54:37 +0000

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

In generale:

a | b

fa in modo che l'output di a diventi l'input di b. Ti consiglio di leggere la sezione Pipelines di man bash.


Se vuoi davvero usare ls e echo insieme ecco alcuni esempi (abbastanza inutili):

ls | xargs -L 1 echo
echo `ls`
for i in `ls` ; do echo $i ; done
13
13
13
2010-09-16 14:03:04 +0000

Se vuoi echo il comando ls prova:

ls | xargs echo

Questo chiamerà echo con l'output di ls.

3
3
3
2011-11-09 09:48:27 +0000

Perché non usare semplicemente:

echo `ls`

O molto più sicuro:

echo "`ls -lrt`"