Here's where the real use case is - I've got a bash script that I'd like to have it just pass stdin to stdout, after it finishes saying something.
$ cat /etc/password | say_and_pass "stage 1" | grep -v test | say "stage 2"
O problema com o que você está tentando fazer aqui é que você parece ter dois fluxos de dados - um para say
e um para processamento de texto (ou seja, cat
e grep
).
Você não pode usar um único pipeline para isso, pois apenas misturará os dados. cat /etc/passwd | say
fará seu computador tentar falar todo o conteúdo do arquivo. Além disso, say
não grava qualquer coisa na saída padrão, então nada iria mais longe no pipeline.
Se você quiser "interromper" seu fluxo de processamento de dados para manipular saída separada para outros utilitários como say
, será necessário configurar um FIFO (ou seja, um "canal nomeado") para um ou outro de seus fluxos de dados ou usar arquivos temporários gravados no disco.
Seu caso de uso demonstrativo não é muito útil para um exemplo, pois apesar do say
s, você está apenas grep
ping em um arquivo, o que pode ser feito em uma etapa com grep -v test /etc/passwd
( cat file | grep pattern
é um uso inútil de cat
).
Tudo o que foi dito, um exemplo usando um arquivo de rascunho:
scratch=$(mktemp)
trap "rm -f $scratch" EXIT
cat /etc/passwd > $scratch
say "Stage one"
grep -v test $scratch
say "Stage two"
E um usou um pipe nomeado para say
:
mkfifo youtalktoomuch
say youtalktoomuch &
exec 3> youtalktoomuch
do_thing_one
echo "Stage one" > youtalktoomuch
do_thing_two
echo "Stage two" > youtalktoomuch
exec 3>&-
rm youtalktoomuch
Once again, though, if you need to connect the output of 'do_thing_one' to the input of 'do_thing_two' without piping one into the other, you will need to use either another named pipe or a scratch file on disk to hold the data.