O que o símbolo do pipe linux "|" faz? [duplicado]

23

Aqui está um comando que classifica os arquivos em uma pasta na ordem inversa

ls | sort -r

O que o |símbolo nesse comando faz?

O que realmente estou procurando aqui é uma explicação de alto nível (fácil de entender) de pipes para iniciantes em Linux. Vejo outras perguntas sobre pipes aqui no Superusuário, mas nada que indique uma resposta que explique em termos simples o que eles fazem e como eles diferem do redirecionamento (o símbolo >ou <).

ccalvert
fonte
7
Isso não tem nada a ver com o Linux (que é um kernel). Os tubos em geral são um meio de redirecionar a entrada / saída, em um shell como o bash não é diferente. A única coisa especial sobre a |é que ele não usa um nome; a saída do comando l-hand é passada diretamente para a entrada do comando no lado r do lado do tubo.
Andon M. Coleman
Para uma história-aula sobre o assunto, leia linfo.org/pipe.html
Fredrik Pihl
ls -1r(Observe o argumento número um) deve produzir um resultado semelhante a ls | sort -r.
Ivan Chau
Eu gosto de explicar dessa maneira: Um canal pega a saída de um comando e a torna utilizável para o seguinte comando. Por exemplo, você pode fazer cat /somefile | grep cool. Isso pegará a saída de somefile e a disponibilizará para grep; depois, o grep imprimirá todas as linhas com a palavra cool.
JohnDoea

Respostas:

26

O seguinte é um pouco simplificado para ajudar novos usuários.

Bem, primeiro, é necessário entender o conceito de entrada e saída padrão.

No Linux e em outros sistemas operacionais do tipo UNIX, cada processo possui uma entrada padrão ( stdin) e uma saída padrão ( stdout). A situação usual stdiné o teclado e stdouta tela ou a janela do terminal.

Então, quando você executa ls, ele lança sua saída para stdout. Se você não fizer mais nada, ele será exibido na tela ou na janela do terminal e você será exibido.

Agora, alguns comandos do Linux interagem com o usuário e costumam stdinfazer isso, sendo seu editor de texto um deles. Ele lê de stdinpara aceitar as teclas digitadas, fazer as coisas e depois gravar as coisas stdout.

No entanto, também existem comandos não interativos ou de "filtro" que NÃO funcionam interativamente, mas desejam um monte de dados. Esses comandos pegam tudo o que stdintem, fazem alguma coisa e jogam parastdout

Vejamos outro comando chamado du- significa uso de disco. du /usr, por exemplo, imprimirá ( stdoutcomo qualquer outro comando do Linux) uma lista de todos os arquivos nesse diretório e seu tamanho:

# du /usr
2312    /usr/games
124     /usr/lib/tc
692     /usr/lib/rygel-1.0
400     /usr/lib/apt/methods
40      /usr/lib/apt/solvers
444     /usr/lib/apt
6772    /usr/lib/gnash

Como você pode dizer logo de cara, ele não está classificado, e você provavelmente o quer em ordem de tamanho.

sorté um daqueles comandos de "filtro" que pega várias coisas stdine as classifica.

Então, se fizermos isso:

# du /usr | sort -nr

nós entendemos isso, que é um pouco melhor:

4213348 /usr
2070308 /usr/lib
1747764 /usr/share
583668  /usr/lib/vmware
501700  /usr/share/locale
366476  /usr/lib/x86_64-linux-gnu
318660  /usr/lib/libreoffice
295388  /usr/lib/vmware/modules
290376  /usr/lib/vmware/modules/binary
279056  /usr/lib/libreoffice/program
216980  /usr/share/icons

E agora você pode ver que o "pipe" conecta o stdoutcomando de um ao stdinoutro. Normalmente, você o utilizará em situações como esta em que deseja filtrar, classificar ou manipular a saída de um comando. Eles podem ser colocados em cascata se você desejar processar a saída por meio de vários comandos do tipo filtro.

Se você digitar sortpor si só, ele ainda tentará ler stdin. Como stdinestá conectado ao teclado, ele estará aguardando você digitar e processar as coisas até pressionar Control-D. Isso não será solicitado, pois não é para ser usado de maneira interativa.

É possível que um programa diga se stdiné interativo ou não; portanto, alguns programas podem agir de maneira diferente se você os emitir sozinhos ou no final de um canal.

Além disso, canalizar um programa que funcione apenas de maneira interativa viresultará em problemas para você.

Os canais são diferentes do redirecionamento, pois os dados são embaralhados de um comando para o outro sem serem armazenados em nenhum lugar. Portanto, no exemplo acima, dua saída de não é armazenada em nenhum lugar. Na maioria das vezes, você não deseja isso com pipes, porque o motivo para usá-los é processar a saída de um comando de alguma maneira - mas existe um comando teeque permite que você pegue o seu bolo e o coma também; copie o que recebe de stdinpara os dois stdoute um arquivo de sua escolha. Você também pode fazer isso bashcom alguma sintaxe misteriosa envolvendo e comercial e colchetes que eu não conheço.

LawrenceC
fonte
Observe que isso não é exclusivo do Linux ou mesmo do POSIX. A maioria dos shells (todos?) No Windows também faz isso. E provavelmente outros sistemas operacionais.
20914 Bob
Conheço o conceito de stdine stdouté diferente no Windows e no Linux, embora provavelmente não muito do ponto de vista do Windows cmd.exeou do Powershell.
LawrenceC
Estou bastante curioso sobre como é diferente - você se importaria de explicar? Talvez no chat, se os comentários não forem um bom lugar para isso.
20414 Bob
1
Os programas Win32 definitivamente possuem uma entrada e saída padrão. Por exemplo, você pode recuperar o identificador padrão de entrada, saída ou erro do seu processo com a função Win32 GetStdHandle(). Também é trivial redirecionar os fluxos padrão de um processo [filho] gerado com o .NET, que eu acredito que mapeia para as funções do Win32 (mas não tenho 100% de certeza disso - não sou um desenvolvedor do Win32).
22414 Bob
1
Ah, aqui está o equivalente do Win32, definindo os parâmetros apropriados na STARTUPINFOestrutura para CreateProcess().
Bob
27

Se você se sentir confortável com o redirecionamento de saída e entrada, a explicação é realmente bastante fácil.

Command1 | Command2

faz o mesmo que

Command1 > tempfile
Command2 < tempfile

mas sem tempfile. A saída de Command1está diretamente conectada à entrada Command2e a transferência ocorre na memória.

Daniel B
fonte
Eu posso estar errado, mas acho que o tempfile existe mesmo na sintaxe do pipe. Apenas não tem nome.
Taemyr
3
Não, não tem. Nenhuma operação do sistema de arquivos está envolvida ao canalizar a saída de um comando para a entrada de outro comando.
Daniel B
1
Porém, no DOS (e provavelmente no Windows), um arquivo temporário é criado pelo canal. Não * nix, mas não vale nada a diferença.
Jeremy J Starcher
Tenho certeza de que isso não está correto. O Process Monitor não reporta CreateFileou faz WriteFilechamadas para apoiar sua reivindicação. / edit: Isso é para a parte do Windows, é claro.
Daniel B
3

Realmente, se você quiser saber o que os pipes fazem e a diferença entre> e |, vá para um diretório com muitos arquivos e

de um terminal ls vs ls | more (ou fazendo isso no Windows com DIR e DIR | MORE)

Se você usou> more, verá que ele cria um arquivo chamado 'more', em vez de enviar a saída de ls para o comando 'more'. Portanto, se alguém fizesse mais, provavelmente seria um erro, não faria mais> você faria> arquivo1. Mais é um comando bem conhecido.

O <como o> também é para vincular um comando e um arquivo, em vez de um comando para um comando. Mas enquanto> envia a saída de um comando para um arquivo, o <envia um arquivo como entrada para um comando. Eu raramente uso <como normalmente uso cat file1 | para enviar a saída de um arquivo para um comando.

$ grep a <arquivo1 abc

$ cat file1 | grep a abc

grep com 2 parâmetros é do arquivo de padrão grep do formulário. grep com um parâmetro é padrão grep. E você pode enviar o arquivo canalizando o conteúdo do arquivo para ele ou usando <. Se estiver usando <, escreva primeiro o nome do comando e, em seguida, o nome do arquivo após o comando <file. Se estiver usando | para canalizar o conteúdo de um arquivo, você usa cat file1 | comando.

Além disso, muitos comandos recebem um arquivo como entrada de qualquer maneira, portanto, o grep a file1 funcionará, assim como o arquivo cat1 | grep a e grep a <arquivo1.

Eu estava fazendo pipes (|) e no DOS até 15 anos atrás.

Para resumir como | difere de <e> - O canal fica entre 2 comandos Os <e> ficam entre um comando e um arquivo. O> é gerado em um arquivo. A <é entrada de um arquivo.

barlop
fonte
3

O caractere de barra vertical ( |) conecta a saída de um programa à entrada de outro.

Neste exemplo, echoimprime a palavra helloe wc -cfaz uma contagem de caracteres de sua entrada:

echo hello | wc -c
bbaassssiiee
fonte
Eu acho que você deveria dizer de uma vez que o eco irá gerar "hello \ n". Você não está dizendo ao OP para estudar, está dizendo isso para todo mundo que lê sua resposta. Por que multiplicar esse desperdício de tempo?
Rodrigo
Obrigado pelo feedback, abreviei minha resposta.
bbaassssiiee
2

Para entender isso, tente você mesmo:

sort -r

Agora você está pendurado com um cursor e não está fazendo nada. O que acontece se você digitar alguns dados?

1
2
3
5
4

Ainda nada, certo? Agora pressione ctrl + D

5
4
3
2
1

Então, o que o tipo faz é pegar a entrada (o que você digitou), faz alguma coisa com ela (classifica) e a devolve como saída. O lscomando não aceita entrada, apenas gera saída. O símbolo de canal retira a saída lse a alimenta como entrada para o sortcomando.

>não alimenta a saída para um programa, mas armazena a saída como um arquivo. <usa um arquivo como entrada.

jornane
fonte