Não existem "regras" como tais. Alguns programas recebem entrada do STDIN e outros não. Se um programa pode receber informações do STDIN, ele pode ser canalizado para, se não, não pode.
Normalmente, você pode dizer se um programa irá receber informações ou não, pensando no que faz. Se o trabalho do programa é de alguma forma manipular os conteúdos de um arquivo (por exemplo grep
, sed
, awk
etc.), que normalmente leva a entrada de STDIN. Se seu trabalho é manipular o arquivo em si (por exemplo mv
, rm
, cp
) ou um processo (por exemplo kill
, lsof
) ou às informações de retorno sobre algo (por exemplo top
, find
, ps
), então isso não acontece.
Outra maneira de pensar sobre isso é a diferença entre argumentos e entrada. Por exemplo:
mv foo bar
No comando acima, mv
não tem entrada como tal. O que foi dado são dois argumentos. Ele não sabe nem se importa com o que está em nenhum dos arquivos, apenas sabe que esses são seus argumentos e deve manipulá-los.
Por outro lado
sed -e 's/foo/bar/' < file
--- -- ------------ ----
| | | |-> input
| | |------------> argument
| |--------------------> option/flag/switch
|------------------------> command
Aqui, sed
foi dada entrada, bem como um argumento. Uma vez que recebe entrada, ela pode ser lida no STDIN e pode ser canalizada para.
Fica mais complicado quando um argumento pode ser a entrada. Por exemplo
cat file
Aqui file
está o argumento que foi dado cat
. Para ser mais preciso, o nome do arquivo file
é o argumento. No entanto, como cat
é um programa que manipula o conteúdo dos arquivos, sua entrada é o que estiver dentro file
.
Isso pode ser ilustrado usando strace
um programa que rastreia as chamadas do sistema feitas por processos. Se cat foo
rodarmos strace
, podemos ver que o arquivo foo
é aberto:
$ strace cat foo 2| grep foo
execve("/bin/cat", ["cat", "foo"], [/* 44 vars */]) = 0
open("foo", O_RDONLY)
A primeira linha acima mostra que o programa /bin/cat
foi chamado e seus argumentos foram cat
e foo
(o primeiro argumento é sempre o próprio programa). Posteriormente, o argumento foo
foi aberto no modo somente leitura. Agora, compare isso com
$ strace ls foo 2| grep foo
execve("/bin/ls", ["ls", "foo"], [/* 44 vars */]) = 0
stat("foo", {st_mode=S_IFREG|0644, st_size=0, ...}) = 0
lstat("foo", {st_mode=S_IFREG|0644, st_size=0, ...}) = 0
write(1, "foo\n", 4foo
Aqui também, ls
tomou-se e foo
como argumentos. No entanto, não há open
chamada, o argumento não é tratado como entrada. Em vez disso, ls
chama a stat
biblioteca do sistema (que não é a mesma coisa que o stat
comando) para obter informações sobre o arquivo foo
.
Em resumo, se o comando que você está executando ler sua entrada, você poderá canalizar para ele; se não, não poderá.
pgrep
,pkill
ekillall
comandos.