そのような「ルール」はありません。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
が呼び出され、その引数がcat
andであったことを示しています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
のコマンドを。