そのような「ルール」はありません。STDINから入力を受け取るプログラムとそうでないプログラムがあります。プログラムがSTDINから入力を取得できる場合、パイプで接続できますが、そうでない場合は接続できません。
通常、プログラムが何をするかを考えることで、プログラムが入力を受け取るかどうかを判断できます。プログラムの仕事は何とか操作することであるならば内容ファイル(例えばのgrep、sed、awkなど)を、それが正常にSTDINからの入力を取ります。その仕事は、ファイル自体を操作することであるならば(例えばmv、rm、cp)またはプロセス(例えばkill、lsof)か何か(例えば、約復帰情報にtop、find、ps)それはしていません。
別の考え方は、引数と入力の違いです。例えば:
mv foo bar
上記のコマンドでmvは、そのような入力はありません。与えられているのは2つの引数です。どちらのファイルに何が含まれているかを知らず、気にしません。それらが引数であることを知っているだけで、操作する必要があります。
一方
sed -e 's/foo/bar/' < file
--- -- ------------ ----
| | | |-> input
| | |------------> argument
| |--------------------> option/flag/switch
|------------------------> command
ここでsedは、入力と引数が与えられています。入力を受け取るので、STDINから読み取ってパイプすることができます。
引数ができたときには、より複雑になること入力。例えば
cat file
ここに、fileに与えられた引数がありますcat。正確には、ファイル名 fileが引数です。ただし、catファイルのコンテンツを操作するプログラムであるため、その入力はの内部のものfileです。
これはstrace、プロセスによって行われたシステム呼び出しを追跡するプログラムを使用して説明できます。をcat foo介して実行するstraceと、ファイルfooが開かれていることがわかります。
$ strace cat foo 2| grep foo
execve("/bin/cat", ["cat", "foo"], [/* 44 vars */]) = 0
open("foo", O_RDONLY)
上記の最初の行は、プログラム/bin/catが呼び出され、その引数がcatandであったことを示していますfoo(最初の引数は常にプログラム自体です)。その後、引数fooは読み取り専用モードで開かれました。さて、これと比較してください
$ 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
ここでも、ls自分自身fooを引数として取りました。ただし、open呼び出しはなく、引数は入力として扱われません。代わりにls、システムのstatライブラリ(statコマンドとは異なります)を呼び出して、ファイルに関する情報を取得しますfoo。
要約すると、実行中のコマンドがその入力を読み取る場合は、パイプすることができます。そうでない場合はできません。
pgrep、pkillとkillallのコマンドを。