没有这样的“规则”。有些程序从STDIN接受输入,有些则没有。如果程序可以从STDIN中获取输入,则可以将其通过管道传递给它,否则不能通过管道传递给它。
您通常可以通过考虑程序的工作来判断程序是否将接受输入。如果程序的任务就是以某种方式操纵内容文件(例如grep,sed,awk等),一般需要从STDIN输入。如果它的工作是操作文件本身(例如mv,rm,cp)或进程(例如kill,lsof),或对某事返回信息(例如top,find,ps),那么它没有。
另一种思考方式是参数和输入之间的区别。例如:
mv foo bar
在上面的命令中,mv没有任何输入。给出了两个论点。它不知道或不在乎这两个文件中的内容,它只是知道这些是其参数,因此应该对其进行操作。
另一方面
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命令不同)以获取有关file的信息foo。
总之,如果您正在运行的命令将读取其输入,则可以通过管道将其输入,如果没有,则不能。
pgrep,pkill和killall命令。