Nie ma „zasad” jako takich. Niektóre programy pobierają dane ze STDIN, a niektóre nie. Jeśli program może pobierać dane wejściowe ze STDIN, może być przesyłany potokowo, jeśli nie, nie może.
Zwykle możesz stwierdzić, czy program pobierze dane, myśląc o tym, co robi. Jeśli praca programu jest w jakiś sposób manipulować zawartość z pliku (np grep
, sed
, awk
etc.), to zwykle trwa wejściowe z stdin. Jeśli jego zadaniem jest manipulowanie sam plik (np mv
, rm
, cp
) lub proces (np kill
, lsof
) lub powrotnej do informacji o czymś (np top
, find
, ps
), to nie.
Innym sposobem myślenia na ten temat jest różnica między argumentami a danymi wejściowymi. Na przykład:
mv foo bar
W powyższym poleceniu mv
nie ma danych wejściowych jako takich. Podano dwa argumenty. Nie wie ani nie obchodzi, co jest w żadnym z plików, po prostu wie, że to są jego argumenty i powinien nimi manipulować.
Z drugiej strony
sed -e 's/foo/bar/' < file
--- -- ------------ ----
| | | |-> input
| | |------------> argument
| |--------------------> option/flag/switch
|------------------------> command
Tutaj sed
podano dane wejściowe oraz argument. Ponieważ pobiera dane wejściowe, może je odczytać ze STDIN i może być przesyłane potokowo.
Staje się bardziej skomplikowane, gdy argumentem może być dane wejściowe. Na przykład
cat file
Oto file
argument, który został podany cat
. Mówiąc ściślej, argumentem jest nazwa pliku file
. Ponieważ jednak cat
jest to program, który manipuluje zawartością plików, jego wejściem jest wszystko, co jest w środku file
.
Można to zilustrować za strace
pomocą programu, który śledzi wywołania systemowe wykonywane przez procesy. Jeśli uruchomimy cat foo
przez strace
, możemy zobaczyć, że plik foo
jest otwarty:
$ strace cat foo 2| grep foo
execve("/bin/cat", ["cat", "foo"], [/* 44 vars */]) = 0
open("foo", O_RDONLY)
Pierwszy wiersz powyżej pokazuje, że program /bin/cat
został wywołany, a jego argumentami były cat
i foo
(pierwszym argumentem jest zawsze sam program). Później argument foo
został otwarty w trybie tylko do odczytu. Teraz porównaj to z
$ 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
Tutaj także ls
wziął siebie i foo
jako argumenty. Jednak nie ma open
wywołania, argument nie jest traktowany jako dane wejściowe. Zamiast tego ls
wywołuje stat
bibliotekę systemową (co nie jest tym samym co stat
polecenie), aby uzyskać informacje o pliku foo
.
Podsumowując, jeśli uruchomione polecenie odczyta jego dane wejściowe, możesz przesłać do niego potokiem, jeśli nie, nie możesz.
pgrep
,pkill
ikillall
poleceń.