No hay "reglas" como tales. Algunos programas reciben información de STDIN y otros no. Si un programa puede recibir información de STDIN, se puede canalizar a, si no, no puede.
Normalmente puede saber si un programa tomará información o no al pensar en lo que hace. Si el trabajo del programa es manipular de alguna forma los contenidos de un archivo (por ejemplo grep
, sed
, awk
etc.), que normalmente toma de entrada de STDIN. Si su trabajo consiste en manipular el archivo en sí (por ejemplo mv
, rm
, cp
) o un proceso (por ejemplo kill
, lsof
) o a la información de retorno sobre algo (por ejemplo top
, find
, ps
), entonces no lo hace.
Otra forma de pensarlo es la diferencia entre argumentos y aportes. Por ejemplo:
mv foo bar
En el comando anterior, mv
no tiene entrada como tal. Lo que se le ha dado son dos argumentos. No sabe ni le importa lo que hay en ninguno de los archivos, solo sabe que esos son sus argumentos y debe manipularlos.
Por otra parte
sed -e 's/foo/bar/' < file
--- -- ------------ ----
| | | |-> input
| | |------------> argument
| |--------------------> option/flag/switch
|------------------------> command
Aquí, sed
se ha dado información y un argumento. Como toma entrada, puede leerlo desde STDIN y puede canalizarlo.
Se vuelve más complicado cuando un argumento puede ser la entrada. Por ejemplo
cat file
Aquí file
está el argumento que se le dio cat
. Para ser precisos, el nombre del archivo file
es el argumento. Sin embargo, dado que cat
es un programa que manipula el contenido de los archivos, su entrada es lo que esté dentro file
.
Esto puede ilustrarse con strace
un programa que rastrea las llamadas al sistema realizadas por los procesos. Si corremos a cat foo
través de strace
, podemos ver que el archivo foo
está abierto:
$ strace cat foo 2| grep foo
execve("/bin/cat", ["cat", "foo"], [/* 44 vars */]) = 0
open("foo", O_RDONLY)
La primera línea de arriba muestra que el programa /bin/cat
fue llamado y sus argumentos fueron cat
y foo
(el primer argumento es siempre el programa en sí). Más tarde, el argumento foo
se abrió en modo de solo lectura. Ahora, compara esto con
$ 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
Aquí también, se ls
tomó y foo
como argumentos. Sin embargo, no hay open
llamada, el argumento no se trata como entrada. En cambio, ls
llama a la stat
biblioteca del sistema (que no es lo mismo que el stat
comando) para obtener información sobre el archivo foo
.
En resumen, si el comando que está ejecutando leerá su entrada, puede canalizarlo, si no lo hace, no puede.
pgrep
,pkill
y loskillall
comandos.