Como a entrada padrão de um programa pode ser passada como um argumento para outro?


17

Digamos que exista um programa, que requer dois argumentos; arquivo de entrada e arquivo de saída.

E se eu não desejar salvar esse arquivo de saída em disco, mas passá-lo diretamente para stdinoutro programa. Existe uma maneira de conseguir isso?

Muitos comandos que encontro no Linux oferecem uma opção para passar '-' como o argumento do arquivo de saída, que faz o que eu especifiquei acima. Isso stdinocorre porque não é possível passar o programa como argumento? Se for, como fazemos?

Um exemplo de como eu criaria imagens usando isso é:

pdftotext "C BY BRIAN W KERNIGHAN & DENNIS M RITCHIE.pdf" stdin(echo)

O shell que estou usando é o bash.


1
cat <file | cmd /dev/fd/0funciona na maioria das unidades.
Mikeerv

Não está trabalhando para mim. Tentou fazê-lo com: cat < README.txt | cp /dev/fd/0. Dissecp: missing destination file operand after ‘/dev/fd/0’ Try 'cp --help' for more information.
Dziugas

1
program input-file /dev/stdout | another-program? Observe também que echonão lê nada do stdin.
Yaegashi

1
@ Dziugas - é claro que não - você não pode cparquivar em nenhum lugar. echo 1 2 3| cp /dev/fd/0 /dev/ttyirá imprimir 1 2 3. E, a propósito, /dev/fd/[num]é mais provável que funcione do que /dev/std(in|out|err)na maioria dos casos. Consulte Portabilidade dos links do descritor de arquivos sobre o que você pode esperar para trabalhar onde.
mikeserv

1
Um bom programa UNIX gravaria na saída padrão, cabendo ao usuário decidir se deseja redirecionar para um arquivo ou canal para outro comando.
Jorge Bucaran

Respostas:


13

Se o programa suportar a gravação em qualquer descritor de arquivo, mesmo que não possa ser procurado, você poderá usá-lo /dev/stdoutcomo arquivo de saída. Este é um link simbólico para o /proc/self/fd/1meu sistema. O descritor de arquivo 1 é stdout.


Isso resolveu minha consulta. Portanto, não há como fazê-lo quando o programa precisa procurar?
Dziugas

3
Se você está tentando impedir o acesso ao disco, pode gravar o arquivo em / dev / shm /, no entanto, se não quiser nenhum arquivo no sistema de arquivos, pelo que sei, não há como procurar um cano. Buscar adiante significa que teria que armazenar em buffer tudo na memória até chegar a esse ponto em frente, e buscar voltar implica colocar em buffer tudo na memória.
TiCPU

pdftotextcomo muitos (mas não todos) outros utilitários também suportam -isso (o que funcionaria mesmo em sistemas que não suportam / dev / stdout, ou onde / dev / stdout não funciona como esperado, como no Linux, onde o stdout não é um cano). pdftotext file.pdf - | wc -c
Stéphane Chazelas

11

Na pdftotextpágina do manual:

Se o arquivo de texto for ´- ', o texto é enviado para stdout.

Portanto, neste caso, tudo que você precisa é:

pdftotext "C BY BRIAN W KERNIGHAN & DENNIS M RITCHIE.pdf" -

Ou se você quiser canalizar isso para STDIN de outro programa:

pdftotext "C BY BRIAN W KERNIGHAN & DENNIS M RITCHIE.pdf" - | another_prog

Usar -como substituto para um nome de arquivo é uma convenção que muitos utilitários seguem (incluindo pdftotext) quando queremos entrada de STDIN ou saída para STDOUT. No entanto, nem todos os utilitários seguem esta convenção. Nesse caso, a maneira idiomática de fazer isso no bash é usar uma substituição de processo :

my_utility "C BY BRIAN W KERNIGHAN & DENNIS M RITCHIE.pdf" >( cat )

Aqui, o >( )comportamento se comporta basicamente como um arquivo passado my_utility, mas, em vez de ser um arquivo real, o fluxo é canalizado para o stdin do processo contido, ou seja, cat. Portanto, aqui, o texto deve ser finalizado conforme necessário.

O uso de catquase sempre aciona os alarmes UUOC em fóruns como este. Eu afirmo que, se o utilitário não suportar -, esse é um uso útil cat, embora, se houver alguma maneira de fazer essa substituição de processo sem o cat, então eu sou todo ouvidos ;-).

No entanto, se (como a pergunta disser) o destino final do fluxo for STDIN de outro programa, ele catpoderá ser eliminado:

my_utility "C BY BRIAN W KERNIGHAN & DENNIS M RITCHIE.pdf" >( another_prog )

2
E deixe-me recuar mais uma vez: se prog2gravar em stdout, é melhor que , porque o formulário aguarda a conclusão (ou seja, antes que o shell emita o próximo prompt ou prossiga para o próximo comando (por exemplo, depois ou )), enquanto o - a menos que o formulário aguarde apenas o preenchimento. Além disso, após o formulário, é o status de saída de , enquanto, no outro, é o status de saída de . (Você paga seu dinheiro e você leva sua escolha.)prog1 input_file >( cat ) | prog2prog1 input_file >( prog2 )catprog2;&&catprog1cat$?prog2$?prog1
Scott

4

Se o seu shell os suportar, a maneira mais simples de fazer essas manipulações seria usar a substituição do processo : <(…)e >(…). Isso funciona no bash, zsh e ksh e possivelmente em outros shells. Por exemplo:

$ sort <(printf "b\nc\na\n")
a
b
c
$ ls
foo
$ cp <(find . -name foo) bar
$ ls
bar  foo

No entanto, isso não ajudará no exemplo que você indicar, pois pdftotextserá salvo em um arquivo de texto. Embora sua melhor opção (além da óbvia de usar -) seja a /dev/stdoutsugestão sugerida pelo @TiCPU, você também pode usar outro recurso de shell. A construção !:Nrefere-se ao enésimo argumento do comando anterior. Portanto, você pode fazer:

$ pdftotext "C BY BRIAN W KERNIGHAN & DENNIS M RITCHIE.pdf"  out.txt
$ cat !:2

1
Embora eu concorde que cat <()possa ser útil em algumas situações, neste cenário, no entanto, não está funcionando. O problema (muito mal descrito pelo OP, devo admitir) é que são pdftotextnecessários dois argumentos: arquivo de entrada e arquivo de saída . Se o segundo argumento estiver ausente, ele não produzirá nada, portanto cat <(pdftotext "file.pdf")também não retornará nada. Pode-se enganar o pdftotextcomando dando >(cat)como segundo argumento o Digital Trauma respondido, mas não cat <()faz sentido aqui. Obviamente, pdftotextcaso seja melhor usar apenas -como o nome do arquivo de saída.
jimmij

1
@ Scott Como minha resposta é um UUOC? Como você faria essa substituição de processo sem gato? >( )efetivamente canalizará o fluxo para qualquer processo que esteja dentro - então, na verdade, precisamos de um cataqui para produzir esse fluxo. Normalmente, devemos ser capazes de fazer algo assim pdftotext input.pdf -, mas aparentemente pdftotextnão suporta o -parâmetro de saída diretamente para stdout em vez de um arquivo - tente.
Digital Trauma

1
@DigitalTrauma não é uuoc. Eu acredito que o gato é o mais rápido que você pode obter no caso de apenas imprimir, mas na verdade você pode usar outro comando >(grep something)para ser mais útil. BTW, meu pdftotext 3.04 Do suporte -como um arquivo de saída, por isso estou um pouco surpreso com toda a discussão.
jimmij

1
@terdon Eu odeio ser um defensor, mas isso não parece funcionar. Especificamente, não é diferente da execução pdftotext "C BY BRIAN W KERNIGHAN & DENNIS M RITCHIE.pdf", que coloca a saída em um arquivo chamado C BY BRIAN W KERNIGHAN & DENNIS M RITCHIE.txt, mas nenhum texto é enviado para STDOUT para canalizar para outro programa.
Digital Trauma

1
@DigitalTrauma que não está sendo um defensor! Esse sou eu sendo um idiota. Obrigado por apontar e nunca se desculpe ao apontar erros. Prefiro que meu erro seja apontado para mim e, portanto, aprenda algo do que deixá-lo lá em toda a sua glória duvidosa.
terdon

-2
cmd tty

ttyretorna o nome do terminal conectado stdout.


Não tenho certeza de como isso responde à pergunta, que consiste em combinar comandos; talvez você expanda com um exemplo de como conseguir isso.
dhag

Eu acho que você está dizendo para verificar com ttyo nome do terminal e, em seguida, usar esse arquivo como saída, por exemplo pdftotext file.pdf /dev/pts/2. Nesse caso, eu concordo.
jimmij

Isso pode ser abreviado / automatizado para ; o que geralmente será equivalente a . Mas essa abordagem pressupõe que o objetivo é exibir a saída de (ou seja, no terminal), e não é isso que a pergunta está perguntando (veja os comentários na resposta de Terdon para obter alguns esclarecimentos sobre o significado da pergunta). prog1  input_file $(tty)prog1  input_file /dev/ttyprog1
Scott
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.