2012-09-12 114 views
3

我想了解管道和重定向命令的真正威力。根据我的理解,|将一个命令结果的输出作为自身的输入。而且,>是帮助输出重定向。如果是这样,了解管道和重定向命令

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

为什么预期。对于我这个命令是行不通的上述命令意味着

  1. 递归扩展名为找到的所有文件。在当前目录下的swp。
  2. 1.的输出并删除所有的结果文件。

仅供参考,是的,我知道如何完成这项任务。它可以通过传递-exec标志来完成。

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

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

+0

'>'是输出重定向。 '<是输入重定向。 – chepner

+3

你被困在标准输入和命令行之间的区别。你想在bash中使用'$()'运算符,或者在find中使用'-exec'选项,或者(也许是你最好的选择)'xargs'。没有能量写出真正的答案... – dmckee

回答

4

我会打破这种下跌已显示的三种方法:

  • >将所有输出重定向从find到一个名为rm(将无法工作文件,因为你只是追加到一个文件)。
  • find
  • |将输出管进入rm命令(将不起作用,因为rm不上stdin读取)
  • -exec rm -rf {} \;将在每个项目上运行rm -rf{}),该find的发现(将工作,因为它通过文件作为参数rm)。

你将要使用-exec标志,或管道进入xargs命令(man xargs),不|>,以达到所期望的行为。

编辑:为@dmckee说,你也可以使用$()操作字符串插值算法,即:rm -rf $(find . -name "*.swp")(如果您有大量的文件,由于参数长度的限制,这将失败)。

+0

你也可以使用shell globbing('rm -rf **/*。swp')来实现你陈述的(例子)目标,但有点超出问题的范围(shell管道和重定向)。 – neersighted

+0

字符串插值正在将标准输出更改为标准输入,是这样的。 –

+0

@亲爱的:不,它不是。在启动程序之前,你的shell会看到'$()',并用'$()'中的命令输出替换它。一个例子说明了这一点。 如果我有'echo'foo $(echo'bar')“',shell会替换'$()',并真正执行'echo”foobar“'。 – neersighted

1

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

我会尽力解释了什么问题你:

find . -name "*.swp" | rm 

该命令将查找结果(即find的stdout)重定向到程序rmstdin。但是,rm未在标准输入读取(这是您可以在rm的文档中阅读的内容)。通过命令行参数控制rm,而不是通过stdin控制。我认为根本没有办法从stdin中读取rm。这就是为什么没有被删除。

find . -name "*.swp" > rm 

此命令会将新行分隔的查找结果(找到的标准输出)到名为“RM”的文件。同样,没有被删除:)

基本上<>>>&>&>>运营商从/到文件,实际上在文件系统中存在执行重定向。管道|将一个命令的标准输出重定向到另一个命令的标准输入。简单地说,这里没有涉及任何文件。然而,这种方法只有在管道左侧的程序实际写入stdout并且管道右侧的程序从stdin两个程序彼此理解,即读取程序(消费者)了解喂养计划的输出。

3

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

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

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

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

导致发现打印sperated到标准输出文件名\ 0和xargs的读\ 0分隔的文件名,并将其作为参数传递给RM。

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

rm **/*.swp 

假设你使用bash。

+0

+1,谢谢你解释xargs。 –

0

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

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

当然,rm不从标准输入读取文件名,所以cmd | rm根本没用(距情况下的管道与不与rm没看过的东西输入另一个命令继续)。如果你想要的话,有xargs

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