进程替换:Linux 中输入/输出重定向的一种不常见但先进的方法
您可能已经熟悉Linux 中的输入/输出和管道重定向。
让我给你介绍一个类似但更高级的功能,称为进程替换。
您会发现两种进程替换的语法:
<(commands)
或者
>(commands)
让我详细地讲一下。
Bash 进程替换
您会发现进程替换可以类似于 STDOUT 或 STDIN 重定向使用。
使用<(commands)
运算符,您可以从替换中读取。这意味着commands
设置为将其用作stdout
。
例如,以下命令使用的输出ls *sh
:
wc -l <(ls *sh)
这相当于:
ls *sh | wc -l
使用>(commands)
运算符,您可以写入替换。这意味着commands
设置为将其用作stdin
。
换句话说,当您有一个输出到文件的命令但您希望它写入其他命令而不是文件时。
以下示例可以让事情更清楚一些:
tar -cf >(ssh remote_server tar xf -) .
您知道它的作用是什么吗?没错。您刚刚将当前目录的所有内容传输到远程服务器。存档文件是即时创建的,并在服务器上提取。
说实话,>(...)
运算符不太常用。你会发现它<(...)
可以更常用。
那么,如果进程替换像常规输入输出重定向一样工作,那么它的优势是什么?
当您有多个命令管道需要组合在单个命令中时,您就会意识到 bash 进程替换的强大功能和实用性。
bash 进程替代的优点
进程替换最明显和最常见的用途是比较两个程序的输出。让我用一个实际的例子来向你展示它。
假设您在目录中有一些 C 程序文件及其对应的同名目标文件(.out 文件)。
ls *
aa.c aa.out bb.c bb.out cc.c cc.out ...
您的目标如下。您想检查每个 C 文件是否都有与其同名的相应输出文件。
典型的方法是列出按扩展名过滤的文件,然后使用带分隔符 .(点)的 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 的一个特性,它可能与其他 shell 一起工作,也可能不工作。
我希望您将来会尝试使用进程替换。正如您所见,它非常有用。欢迎您提出问题和建议。