了解管道和重定向命令

时间:2012-09-12 18:44:47

标签: bash pipe

我想了解管道和重定向命令的实际功能。根据我的理解,|将一个命令结果的输出作为自身的输入。并且,>有助于输出重定向。如果是,

find . -name "*.swp" | rm 
find . -name "*.swp" > rm 

为什么这个命令没有按预期工作。对我来说,上面的命令意味着

  1. 以递归方式查找当前目录中扩展名为.swp的所有文件。
  2. 获取1.的输出并删除所有生成的文件。
  3. 仅供参考,是的,我知道如何完成这项任务。可以通过传递-exec标志来完成。

    find . -name "*.swp"-exec rm -rf {} \;
    

    但正如我已经提到的,我想用>|命令完成它 如果我错了,走向错误的方向,请纠正我并解释重定向和管道命令。我们在哪里使用哪些命令?请不要提到简单的书籍例子我读了所有的东西。试着向我解释一些复杂的事情。

4 个答案:

答案 0 :(得分:4)

我会用你展示的三种方法来解决这个问题:

  • >会将find的所有输出重定向到名为rm的文件中(不起作用,因为您只是附加到文件中)。
  • |会将find的输出管道输入rm命令(不起作用,因为rm未读取stdin
  • -exec rm -rf {} \;将对rm -rf找到的每个项目{}运行find(将起作用,因为它将文件作为参数传递给rm

您需要使用-exec标记或管道输入xargs命令(man xargs),而不是|>才能实现期望的行为。

编辑:正如@dmckee所说,您也可以使用$()运算符进行字符串插值,即:rm -rf $(find . -name "*.swp")(如果您有大量的字符串插入,则会失败文件,由于参数长度限制)。

答案 1 :(得分:3)

>只需重定向到名为rm的文件。 管道通过|到rm不起作用,因为rm不期望通过STDIN提供文件名。 所以你必须使用xargs,它将STDIN中的值作为参数传递:

find . -name "*.swp"|xargs rm

这很危险,因为文件名可能包含shell认为字段分隔符($ IFS)的字符。 所以,你使用:

find . -name "*.swp" -print0|xargs -0 rm

导致查找打印文件名\ 0分配给STDOUT和xargs读取文件名\ 0分隔并将它们作为参数传递给rm。

当然,实现这一目标的最简单方法是:

rm **/*.swp

假设您使用bash。

答案 2 :(得分:1)

你应该花一些时间再读一下shell重定向的基础知识:)我认为这是一个很好的文档:http://wiki.bash-hackers.org/howto/redirection_tutorial

我会试着解释一下你出了什么问题:

find . -name "*.swp" | rm 

此命令将查找结果(即查找的stdout)重定向到程序stdin的{​​{1}}。但是,rm不会读取stdin(这是您可以在rm的文档中阅读的内容)。 rm是通过命令行参数控制的,而不是通过rm控制的。我认为没有办法让stdin从stdin读取。这就是为什么没有删除。

rm

此命令将换行符分隔的查找结果(查找的stdout)重定向到名为“rm”的文件。没有删除任何内容:)

基本上,find . -name "*.swp" > rm <>>>&>运营商会执行从/到文件的重定向实际上存在于文件系统中。管道&>>将标准输出从一个命令重定向到另一个命令的标准输入。简单地说,这里没有涉及文件。但是,这种方法只有在管道左侧的程序实际写入|并且管道右侧的程序从stdout 读取时才有意义程序相互理解,即阅读程序(消费者)理解喂养程序的输出。

答案 3 :(得分:0)

重定向会创建一个文件。因此,您的>rm示例只会创建一个名为./rm的文件,您的命令输出将保存到该文件中。

管道本质上是一种速记。 one | twoone >tmp; two <tmp类似,只是没有(显式)临时文件。

当然,rm不会从标准输入中读取文件名,因此cmd | rm基本上没用(除了管道继续执行另一个命令的情况,该命令对输入执行{ {1}}没读过)。如果你想要,那就是rm

xargs