进程替换:一种不常见但先进的 Linux 输入/输出重定向方式

您可能已经熟悉 Linux 中的输入/输出和管道重定向。

让我告诉您一个类似但高级的功能,称为进程替换。

您会发现两种用于进程替换的语法:

<(commands)

或者

>(commands)

让我详细一点。

Bash 进程替换

您会发现可以使用类似于 STDOUT 或 STDIN 重定向的进程替换。

<(commands) 运算符,您从替换中读取。 这意味着 commands 设置为将其用作 stdout.

为了 example,以下命令使用的输出 ls *sh

wc -l <(ls *sh)

这相当于:

ls *sh | wc -l

>(commands) 运算符,您写入替换。 这意味着 commands 设置为将其用作 stdin.

换句话说,当您有一个输出到文件的命令但您希望它写入其他命令而不是文件时。

这是一个 example 这应该让事情更清楚一点:

tar -cf >(ssh remote_server tar xf -) .

你知道它是做什么的吗? 这是正确的。 您刚刚将当前目录的所有内容传输到远程服务器。 存档文件是动态创建的,并在服务器上提取。

老实说, >(...) 运算符不太常见。 你会发现 <(...) 可以更频繁地使用。

那么,如果进程替换像常规输入输出重定向一样工作,那么它的优势是什么?

你会意识到它的力量和用处 bash 当您有多个命令管道要组合在一个命令中时,进程替换。

的优势 bash 过程替代

进程替换最明显和最频繁的使用是比较两个程序的输出。 让我用一个实用的方法给你看 example.

假设您在一个目录中有一些同名的 C 程序文件及其对应的目标文件(.out 文件)。

ls *
aa.c aa.out bb.c bb.out cc.c cc.out ...

这是你的目标。 您想检查每个 C 文件是否具有与 C 文件同名的相应输出文件。

您的典型方法是列出按扩展名过滤的文件,然后使用带有分隔符 .(dot) 的 cut 命令提取不带扩展名的文件名:

ls *.c | cut -d. -f1
aa
bb
cc
dd

您的典型方法是将 *.c 和 *.out 文件的输出保存到临时文件中,然后将这些文件与 diff 命令进行比较。 我对吗?

ls *.c | cut -d. -f1 > c.txt
ls *.out | cut -d. -f1 > out.txt
diff c.txt out.txt
rm c.txt out.txt

您可以使用 /tmp 目录来创建临时文件,但仍然有三行命令。

您可以漂亮地使用进程替换来用单个命令替换上述所有内容,而无需创建临时文件:

diff <(ls *.c | cut -d. -f1) <(ls *.out | cut -d. -f1)

您不需要在这里创建任何临时文件,这就是它的关键。 这是我关于何时应该使用进程替换的提示。

每当您认为需要一个临时文件来做某事时,请考虑是否可以使用进程替换。

进程替换是 bash 功能,可能会也可能不会与其他外壳一起使用。

我希望您将来会尝试使用流程替换。 如您所见,它非常有用。 我欢迎您提出问题和建议。