我想了解管道和重定向命令的实际功能。根据我的理解,|
将一个命令结果的输出作为自身的输入。并且,>
有助于输出重定向。如果是,
find . -name "*.swp" | rm
find . -name "*.swp" > rm
为什么这个命令没有按预期工作。对我来说,上面的命令意味着
1.
的输出并删除所有生成的文件。仅供参考,是的,我知道如何完成这项任务。可以通过传递-exec
标志来完成。
find . -name "*.swp"-exec rm -rf {} \;
但正如我已经提到的,我想用>
或|
命令完成它
如果我错了,走向错误的方向,请纠正我并解释重定向和管道命令。我们在哪里使用哪些命令?请不要提到简单的书籍例子我读了所有的东西。试着向我解释一些复杂的事情。
答案 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 | two
与one >tmp; two <tmp
类似,只是没有(显式)临时文件。
当然,rm
不会从标准输入中读取文件名,因此cmd | rm
基本上没用(除了管道继续执行另一个命令的情况,该命令对输入执行{ {1}}没读过)。如果你想要,那就是rm
。
xargs