Главное отличие состоит в том, что <(
... )
, называемый «замена процесса», преобразуется оболочкой в имя файла, которое передается в качестве регулярного аргумента команде; он ничего не посылает на стандартный ввод команды. Это означает, что он не может быть использован непосредственно с такими командами, как tr
, которые не принимают в имени файла аргумент:
$ tr a-z A-Z <(echo hello)
usage: tr [-Ccsu] string1 string2
tr [-Ccu] -d string1
tr [-Ccu] -s string1
tr [-Ccu] -ds string1 string2
Однако, вы всегда можете поставить другой <
перед <(
... )
, чтобы включить это во входном перенаправление вместо:
$ tr a-z A-Z < <(echo hello)
HELLO
И потому, что он генерирует имя файла, вы можете использовать процесс замещение с командами, которые имеют более одного файл аргумент:
$ diff -u <(echo $'foo\nbar\nbaz') <(echo $'foo\nbaz\nzoo')
--- /dev/fd/63 2016-07-15 14:48:52.000000000 -0400
+++ /dev/fd/62 2016-07-15 14:48:52.000000000 -0400
@@ -1,3 +1,3 @@
foo
-bar
baz
+zoo
Другая существенная разница в том, что труба создает подоболочки, которые не могут иметь побочные эффекты в родительской среде:
$ echo hello | read x
$ echo $x
# nothing - x is not set
Но с подменой процесса, только процесс внутри скобок находится в субоболочке; не окружающая команда все еще может иметь побочные эффекты:
$ read x < <(echo hello)
$ echo $x
hello
Стоит отметить, что вы также можете написать в процесс с >(
... )
, хотя меньше случаев, когда это полезно:
$ echo hello > >(cat)
hello
О, это действительно здорово! Спасибо за ответ, который отлично отвечает на мой вопрос. –