3

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

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

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

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

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

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

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

4

4 回答 4

4

我将通过您展示的三种方法对此进行分解:

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

您将需要使用-exec标志或管道进入xargs命令 ( man xargs),而不是|为了>实现所需的行为。

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

于 2012-09-12T18:48:15.387 回答
3

> 简单地重定向到一个名为 rm 的文件。管道通过 | to rm 不起作用,因为 rm 不希望通过STDIN获得文件名。所以你必须使用 xargs,它将来自 STDIN 的值作为参数传递:

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

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

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

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

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

rm **/*.swp

假设你使用 bash。

于 2012-09-12T18:55:12.527 回答
1

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

我将尝试解释您出了什么问题:

find . -name "*.swp" | rm 

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

find . -name "*.swp" > rm 

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

基本上<, , >, >>, &>,运算符执行从/到文件系统中实际存在的文件&>>的重定向。管道将标准输出从一个命令重定向到另一个命令的标准输入。简单地说,这里不涉及任何文件。但是,这种方法只有在管道左侧的程序实际写入内容并且管道右侧的程序从中读取并且两个程序相互理解时才有意义,即读取程序(消费者)理解输出喂食计划。|stdoutstdin

于 2012-09-12T18:48:34.030 回答
0

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

管道本质上是一种速记。one | two就像one >tmp; two <tmp除了没有(显式)临时文件。

当然,rm不会从标准输入中读取文件名,因此cmd | rm基本上是无用的(除了管道继续执行另一个命令的情况,该命令rm对未读取的输入执行某些操作)。如果你想要,有xargs.

find . -name "*.swp" | xargs rm 
于 2012-09-12T18:55:18.377 回答