Sha*_*ain 96 linux cygwin exec find
我想知道到底是什么{} \;和{} \+和| xargs ...做的.请用解释澄清这些.
以下3个命令运行并输出相同的结果,但第一个命令需要一点时间,格式也略有不同.
find . -type f -exec file {} \;
find . -type f -exec file {} \+
find . -type f | xargs file
Run Code Online (Sandbox Code Playgroud)
这是因为第一个file为来自命令的每个文件运行find命令.所以,基本上它运行如下:
file file1.txt
file file2.txt
Run Code Online (Sandbox Code Playgroud)
但后两个-exec命令运行文件命令一次为所有文件,如下所示:
file file1.txt file2.txt
Run Code Online (Sandbox Code Playgroud)
然后我运行以下命令,第一个运行没有问题,但第二个给出错误消息.
find . -type f -iname '*.cpp' -exec mv {} ./test/ \;
find . -type f -iname '*.cpp' -exec mv {} ./test/ \+ #gives error:find: missing argument to `-exec'
Run Code Online (Sandbox Code Playgroud)
对于命令{} \+,它给我错误消息
find: missing argument to `-exec'
Run Code Online (Sandbox Code Playgroud)
这是为什么?任何人都可以解释我做错了什么?
Lek*_*eyn 183
对于每个结果,command {}执行.所有出现的{}都被文件名替换.;带有斜杠前缀以防止shell解释它.
每个结果都附加到后面command并执行.考虑到命令长度限制,我猜这个命令可能会被执行多次,手册页支持我:
命令的调用总数将远远少于匹配文件的数量.
请注意手册页中的引用:
命令行的构建方式与xargs构建命令行的方式大致相同
这就是为什么在空白之间{}和+空白之间不允许使用任何字符的原因.+使find检测到参数应该附加到命令就像xargs.
幸运的是,GNU实现mv可以接受目标目录作为参数,具有任一-t或更长的参数--target.它的用法是:
mv -t target file1 file2 ...
Run Code Online (Sandbox Code Playgroud)
你的find命令变为:
find . -type f -iname '*.cpp' -exec mv -t ./test/ {} \+
Run Code Online (Sandbox Code Playgroud)
从手册页:
-exec命令;
执行命令; 如果返回0状态,则返回true.查找的所有后续参数都被视为命令的参数,直到由`;'组成的参数为止 遇到了.字符串`{}'被在命令参数中出现的任何位置处理的当前文件名替换,而不仅仅是在某些版本的find中的参数中.这两种结构都可能需要进行转义(使用"\")或引用以保护它们不被shell扩展.有关使用-exec选项的示例,请参阅"示例"部分.为每个匹配的文件运行一次指定的命令.该命令在起始目录中执行.围绕使用-exec操作存在不可避免的安全问题; 你应该使用-execdir选项.
-exec命令{} +
-exec操作的此变体在所选文件上运行指定的命令,但命令行是通过在末尾附加每个选定的文件名来构建的; 命令的调用总数将远远少于匹配文件的数量.命令行的构建方式与xargs构建命令行的方式大致相同.命令中只允许一个"{}"实例.该命令在起始目录中执行.
我在Mac OSX上使用ZSH shell 遇到了同样的问题:在这种情况下没有-t选项mv,所以我必须找到另一个解决方案.但是以下命令成功:
find .* * -maxdepth 0 -not -path '.git' -not -path '.backup' -exec mv '{}' .backup \;
Run Code Online (Sandbox Code Playgroud)
秘密是引用括号.不需要大括号就在exec命令的末尾.
我在Ubuntu 14.04下测试(使用BASH和ZSH shell),它的工作原理相同.
但是,在使用+符号时,似乎确实必须在exec命令的末尾.
不支持的实现或不支持的实现find -iname ... -exec mv -t dest {} +的标准等效方法是使用 shell 重新排序参数:find-inamemv-t
find . -name '*.[cC][pP][pP]' -type f -exec sh -c '
exec mv "$@" /dest/dir/' sh {} +
Run Code Online (Sandbox Code Playgroud)
通过使用-name '*.[cC][pP][pP]',我们还可以避免依赖当前区域设置来决定cor的大写版本p。
请注意+, 相反;在任何 shell 中都不是特殊的,因此不需要引用(尽管引用不会造成损害,当然除了像这样的 shellrc不支持\作为引用运算符)。
尾随/是/dest/dir/因为在只找到一个文件且不存在或不是目录(或目录的符号链接)的情况下mv会因错误而失败,而不是重命名为foo.cpp。/dest/dircpp/dest/dir
| 归档时间: |
|
| 查看次数: |
160203 次 |
| 最近记录: |