Здесь нет «правил» как таковых. Некоторые программы принимают входные данные от 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
была вызвана и ее аргументы были cat
и 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
команде.