Enquanto a boa resposta da choroba cura o seu problema, a razão para o comportamento que você notou é o comportamento padrão do pipeline no bash (e eu suponho na maioria dos shells também).
Conforme descrito na seção man bash
pipelines:
The standard output of command is connected via a pipe to the standard input of command2. This connection is performed before any redirections specified by the command (see REDIRECTION below).
Isso significa que stderr
de command1
não é alimentado por padrão para command2
através do pipe, mas é direcionado para seu tty, o link stderr padrão.
O manual do Bash também diz:
If |& is used, command's standard error, in addition to its standard output, is connected to command2's standard input through the pipe; it is shorthand for 2>&1 |.
Portanto, no seu caso, se você deseja canalizar para o comando grep, os erros do comando de localização, que por padrão são enviados para /dev/stderr
, você precisa usar um destes dois formulários:
find / |& fgrep somestuff.ext
find / 2>&1 | fgrep somestuff.ext
Sua queston também pode ser chamada "Por que o stderr é ignorado por pipes".
E a resposta é porque é assim que o bash e o linux são feitos por padrão; tratar stdout
diferentemente de stderr
, para que o usuário seja capaz de registrar / tratar essas duas saídas de maneira diferente.
Por exemplo, você pode canalizar stdout
do comando1 para stdin
do comando2 e, ao mesmo tempo, pode enviar stderr
do comando1 para um arquivo de log usando 2>errorlog.txt
.
Na verdade, quando você executa um comando sem nenhum redirecionamento especificado como
find /
É equivalente a
find / 1>/dev/stdout 2>/dev/stderr
Qual é finalmente resolvido para:
find / 1>/dev/tty1 2>/dev/tty1 #assuming that you are logged in tty1
como pode ser verificado por um único ls
:
ls -all /dev/st*
lrwxrwxrwx 1 root root 15 Nov 25 15:36 /dev/stderr -> /proc/self/fd/2
lrwxrwxrwx 1 root root 15 Nov 25 15:36 /dev/stdin -> /proc/self/fd/0
lrwxrwxrwx 1 root root 15 Nov 25 15:36 /dev/stdout -> /proc/self/fd/1
ls -all /proc/self/fd/2
lrwx------ 1 root root 64 Nov 28 02:46 /proc/self/fd/2 -> /dev/tty1
ls -all /proc/self/fd/1
lrwx------ 1 root root 64 Nov 28 02:46 /proc/self/fd/1 -> /dev/tty1
Se, por algum motivo, você quiser "associar" stdout
e stderr
de um comando, será necessário declarar explicitamente suas finalidades como bash
usando |&
(para pipelines) ou 2>&1
(para qualquer tipo de redirecionamento de saída)