为什么在bash脚本中应该避免管道?

为什么在bash脚本中应该避免管道?,bash,pipe,Bash,Pipe,大多数时候,我看到有人建议在bash脚本中使用管道,有人指出不要使用管道,而是只使用一个命令 例如: find $dir -name $pattern 而不是 ls $dir | grep $pattern 除了避免使用管道,还有其他原因吗?管道本身没有问题。应该避免的是无用的fork() 如果某件事可以在一个过程中完成,通常比使用两个过程来获得相同的结果要好 因为管道创建了一个新流程。在您的示例中,ls和grep是两个进程,find是一个进程。一个或多个管道使命令变慢。一个简单的例子: $

大多数时候,我看到有人建议在bash脚本中使用管道,有人指出不要使用管道,而是只使用一个命令

例如:

find $dir -name $pattern
而不是

ls $dir | grep $pattern

除了避免使用管道,还有其他原因吗?

管道本身没有问题。应该避免的是无用的
fork()


如果某件事可以在一个过程中完成,通常比使用两个过程来获得相同的结果要好

因为管道创建了一个新流程。在您的示例中,ls和grep是两个进程,find是一个进程。一个或多个管道使命令变慢。一个简单的例子:

$ time find Downloads -name *.pdf &>/dev/null

real    0m0.019s
user    0m0.012s
sys 0m0.004s

$ time ls Downloads | grep pdf &>/dev/null

real    0m0.021s
user    0m0.012s
sys 0m0.004s

您不应该解析ls的输出:您知道这两个命令之间有区别吗?“查找”还会搜索子目录。ls没有。@fancyPants是的,确切的命令应该是“ls$dir | grep-I$pattern”和“find$dir-maxdepth 1-iname'$patter'-exec basename\{}.po\”,这些命令应该得到相同的输出,但find命令似乎要复杂得多。但问题更多的是关于管道的,原则上是正确的,但也有不同的语义
ls
还按字母顺序对输出进行排序,而
find
只使用底层系统命令返回的顺序。另外,正如已经指出的,
find
是递归的。您在这里只是
time
-ing
ls
,而不是grep@W.曼恩:啊,事实上,对于内置的
bash
时间,情况就是这样。我认为所需的
exec
fork
成本更高。有人有数字吗?你可以很容易地测试它,但是fork()涉及创建一个新进程、复制当前进程、使用锁定等等,而execl只是替换当前进程。复制当前进程?您必须复制上下文,但不能复制内存本身。至少在Linux中,
fork
是基于写上复制实现的。@W.Mann是的,您是正确的,因为可写页面是写上复制的。但是链接到它们的页面表必须被复制,加上所有打开的文件描述符,等等。