Compreendendo como as entradas são enviadas para os pipes no Bash

17

Eu não entendo muito bem como os tubos funcionam no bash.

Eu sei que é preciso uma saída de um comando como a entrada em outro comando.

Que saída posso obter, porque é o que o comando imprime na tela.

Mas como sei que entrada um comando receberá?

Aqui está um exemplo que eu pensei que iria funcionar:

which gem | rm

Infelizmente não.

Qual gema é impressa para /usr/bin/gemque a saída seja correta?

Eu pensei que isso foi dado à empresa, então seria, rm /usr/bin/gemmas eu estava errado.

Portanto, minha pergunta é: como sei que entrada um comando recebe?

ajsie
fonte
2
Além de qualquer outra coisa, rm /usr/bin/gemé uma péssima ideia. Deixe isso gem(e Ruby intérprete ele vai com) sozinho e instalar o interpretador Ruby preferencial (e gem) usando rvm: rvm.beginrescueend.com
Telêmaco

Respostas:

23

"Entrada" e "argumentos da linha de comando" são coisas diferentes.

rm remove os arquivos fornecidos como argumentos.

Um canal redireciona a saída do comando à esquerda para a entrada do comando à direita. Não afeta os argumentos de linha de comando do programa à direita.

Para fazer o que você está tentando fazer, tente usar xargsa conversão de entrada padrão em argumentos de linha de comando para executar um programa. Esse é o seu trabalho.

which gem | xargs rm, por exemplo, removerá o gemem seu PATH.

Borealid
fonte
12

rmnão aceita entrada, requer argumentos. Estes são diferentes. Os argumentos são as opções e nomes de arquivos e assim por diante que você fornece a um programa na linha de comando para afetar seu comportamento. Entrada são os dados em que o programa trabalha. Por exemplo, grepusa entrada e argumentos:

grep "foo" file.txt

Existem dois argumentos lá "foo"e file.txt. A entrada é o conteúdo de file.txt, não a sequência em file.txtsi. Como o grep recebe entrada, você pode usá-lo com pipes:

cat file.txt | grep "foo"

produz a mesma saída, pois cat está usando file.txtcomo argumento e produzindo o conteúdo de file.txtcomo saída. Essa saída é canalizada para grep, dando o mesmo efeito que o grep abra o próprio arquivo, como no primeiro exemplo.

Se você deseja usar a saída de um programa como argumento para outro, use backticks:

rm `which gem`

ou esta sintaxe alternativa (específica do bash):

rm $(which gem)

Editar: ou xargscomo outro respondente aponta. Muitas maneiras de esfolar um gato com uma linha de comando.

Tyler McHenry
fonte
Vale a pena notar que cat file.txt | grep "foo"pode ser centenas de vezes mais lento que grep "foo" file.txt.
Borealid
1
Esta é a parte que eu não entendo. como sei o que é um argumento e o que é entrada padrão?
ajsie
8
@ajsie: Se você digitar após o nome do programa e antes de pressionar enter, é um argumento. Se você digitar no programa após o início da execução, é uma entrada padrão.
Borealid
1
Entendi! Isso explicava tudo. Agora eu sei que posso usar o comando diretamente e ver se ele me solicita (grep) e também posso ler o manual (man grep) para ver se ele usa entrada std.
ajsie
@ajsie: Se você não quiser mergulhar na página de manual, também grep --helphá uma rápida visão geral dos argumentos aceitos.
Borealid
3

Confira as manpáginas de comandos nos quais você está interessado. Esses programas indicam que eles lêem stdin(tente man grepum comando popular que leia stdin).

dedal
fonte
Eu tentei man grep | grep 'standard input'e consegui If no file arguments are specified, the standard input is used.a última partida. Eu tive que grepprovar um pouco do seu próprio remédio. 😎
ma11hew28
2

Tudo isso é perigoso para executar se você tiver um diretório no PATH que contenha espaço ou se o nome do comando contiver espaço:

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

O GNU Parallel http: // www.gnu.org/software/parallel/ não tem esse problema, portanto isso funcionará mesmo se você tiver um diretório no PATH que contenha espaço ou se o nome do comando contiver espaço:

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

Assista ao vídeo de introdução do GNU Parallel: http://www.youtube.com/watch?v=OpaiGYxkSuQ

Ole Tange
fonte