Comprensione del modo in cui gli input vengono inviati alle pipe in Bash


17

Non capisco bene come funzionano le pipe in bash.

So che prende un output da un comando come input in un altro comando.

Che output posso ottenere perché è ciò che il comando stampa sullo schermo.

Ma come faccio a sapere quale input prenderà un comando?

Ecco un esempio che pensavo avrebbe funzionato:

which gem | rm

Sfortunatamente no.

Quale gemma viene stampata in /usr/bin/gemmodo che debba essere l'output giusto?

Ho pensato che fosse stato dato a RM, quindi sarebbe rm /usr/bin/gemstato un errore, ma mi sbagliavo.

Quindi la mia domanda è: come faccio a sapere quale input prende un comando?


2
A parte tutto, rm /usr/bin/gemè un'idea terribile . Lasciare gem(e l'interprete Ruby a cui si accompagna) da solo e installare il tuo interprete Ruby preferito (e gem) usando rvm: rvm.beginrescueend.com
Telemaco

Risposte:


23

"Input" e "argomenti della riga di comando" sono cose diverse.

rm rimuove i file forniti come argomenti.

Una pipe reindirizza l'output del comando di sinistra sull'input del comando di destra. Non influisce sugli argomenti della riga di comando del programma a destra.

Per fare ciò che stai cercando di fare, prova a utilizzare xargsper convertire l'input standard in argomenti della riga di comando per l'esecuzione di un programma. Questo è il suo lavoro.

which gem | xargs rm, ad esempio, rimuoverà il gemnel PERCORSO.


12

rmnon accetta input, accetta argomenti. Questi sono diversi Gli argomenti sono le opzioni e i nomi dei file e così via che si danno a un programma sulla riga di comando per influenzarne il comportamento. L'input è il dato su cui lavora il programma. Ad esempio, grepaccetta sia input che argomenti:

grep "foo" file.txt

Ci sono due argomenti lì "foo"e file.txt. L' input è il contenuto di file.txt, non la stringa file.txtstessa. Poiché grep accetta input, puoi usarlo con i pipe:

cat file.txt | grep "foo"

produce lo stesso output, poiché cat sta prendendo file.txtcome argomento e produce il contenuto di file.txtcome output. Quell'output viene quindi reindirizzato a grep, dando lo stesso effetto di aver aperto grep il file stesso, come nel primo esempio.

Se si desidera utilizzare l'output di un programma come argomento per un altro, utilizzare i backtick:

rm `which gem`

o questa sintassi alternativa (specifica per bash):

rm $(which gem)

Modifica: o xargscome sottolinea un altro risponditore. Molti modi per scuoiare un gatto con una riga di comando.


Vale la pena notare che cat file.txt | grep "foo"può essere centinaia di volte più lento di grep "foo" file.txt.
Borealid,

1
questa è la parte che non capisco. come faccio a sapere cos'è un argomento e cos'è l'input standard?
ajsie,

8
@ajsie: se lo digiti dopo il nome del programma e prima di premere invio, è un argomento. Se lo digiti nel programma dopo l'avvio, è un input standard.
Borealid,

1
Fatto! Questo ha spiegato tutto. Ora so che entrambi posso usare direttamente il comando e vedere se mi viene richiesto (grep) e potrei anche leggere il manuale (man grep) per vedere se usa l'input std.
ajsie,

@ajsie: se non vuoi immergerti nella manpage, c'è anche grep --helpuna rapida panoramica degli argomenti accettati.
Borealid,

3

Dai un'occhiata alle manpagine dei comandi che ti interessano. Questi programmi indicheranno che hanno letto stdin(prova man grepun comando popolare che legge stdin).


Ho provato man grep | grep 'standard input'e ottenuto If no file arguments are specified, the standard input is used.come ultima partita. 👍 Ho dovuto dare grepun piccolo assaggio della sua stessa medicina. 😎
ma11hew28,

2

Questi sono tutti pericolosi da eseguire se nel tuo PERCORSO è presente una directory che contiene spazio o se il nome del comando contiene spazio:

rm `which gem`       # Dangerous
rm $(which gem)      # Dangerous
which gem | xargs rm # Dangerous

GNU Parallel http: // www.gnu.org/software/parallel/ non ha questo problema, quindi funzionerà anche se nel tuo PERCORSO è presente una directory che contiene spazio o se il nome del comando contiene spazio:

which gem | parallel rm
parallel -a <(which bass) rm

Guarda il video introduttivo per GNU Parallel: http://www.youtube.com/watch?v=OpaiGYxkSuQ

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.