use*_*own 37 shell find xargs quoting
GNU find 的手册页指出:
Run Code Online (Sandbox Code Playgroud)-exec command ; [...] The string `{}' is replaced by the current file name being processed everywhere it occurs in the arguments to the command, not just in arguments where it is alone, as in some versions of find. Both of these constructions might need to be escaped (with a `\') or quoted to protect them from expansion by the shell.
那是从人到find(GNU findutils)4.4.2。
现在我用 bash 和 dash 测试了这个,两者都不需要{}被屏蔽。这是一个简单的测试:
find /etc -name "hosts" -exec md5sum {} \;
Run Code Online (Sandbox Code Playgroud)
是否有一个外壳,我真的需要掩盖大括号?请注意,它不取决于找到的文件是否包含空白(从 bash 调用):
find ~ -maxdepth 1 -type d -name "U*" -exec ls -d {} \;
/home/stefan/Ubuntu One
Run Code Online (Sandbox Code Playgroud)
如果找到的文件被传递到子shell,这会发生变化:
find ~ -maxdepth 3 -type d -name "U*" -exec bash -c 'ls -d {}' \;
ls: cannot access /home/stefan/Ubuntu: No such file or directory
ls: cannot access One: No such file or directory
Run Code Online (Sandbox Code Playgroud)
可以通过以下方式解决:
find ~ -maxdepth 3 -type d -name "U*" -exec bash -c 'ls -d "$0"' {} \;
Run Code Online (Sandbox Code Playgroud)
相比之下:
find ~ -maxdepth 3 -type d -name "U*" -exec bash -c 'ls -d "{}"' \;
/home/stefan/Ubuntu One
Run Code Online (Sandbox Code Playgroud)
但这不是手册页所讨论的内容,是吗?那么哪个 shell 的处理{}方式不同呢?
Gil*_*il' 28
简介: 如果曾经有一个可扩展的 shell {},那么它现在真的是老旧的东西了。
在 Bourne shell 和符合 POSIX 的 shell 中,大括号 ( {and }) 是普通字符(不同于(and)是单词分隔符,如;and &,and[和 and]是通配符)。以下字符串都应该按字面打印:
$ echo { } {} {foo,bar} {1..3}
{ } {} {foo,bar} {1..3}
Run Code Online (Sandbox Code Playgroud)
由单个大括号组成的单词是保留字,只有在它是命令的第一个单词时才特殊。
Ksh 将大括号扩展实现为与 Bourne shell 不兼容的扩展。这可以关闭set +B。Bash 在这方面模仿了 ksh。Zsh 也实现了大括号扩展;在那里它可以用set +I或setopt ignore_braces或关闭emulate sh。这些炮弹都没有扩大{}在任何情况下,即使它是一个字(如的一个子foo{}bar),由于参数共同使用find和xargs。
在某些历史系统中,花括号被视为控制运算符。为了协助未来的标准化活动,可移植应用程序应避免使用不带引号的大括号来表示字符本身。这可能是在ISO / IEC 9945-2的未来版本:1993年标准可能要求
{与}单独视为控制操作,虽然令牌{}可能是因为经常使用的从这个特殊的情况下豁免find{}结构。
此注释在标准的后续版本中被删除;的示例find有未加引号的 使用{}, 的示例也是如此xargs。可能必须{}引用历史上的 Bourne shell ,但它们现在已经是非常古老的遗留系统了。
我手头的 csh 实现(OpenBSD 4.7,Debian 上的 BSD csh,tcsh)都扩展{foo}到foo但{}不理会。
Sté*_*las 15
在{}需要的版本被引用fish之前3.0.0外壳。
$ fish -c 'echo find -exec {} \;'
find -exec ;
Run Code Online (Sandbox Code Playgroud)
在 rc shell 中(也akanga基于rc,但不是基于es):
$ rc -c "echo find -exec {} ';'"
line 1: syntax error near '{'
Run Code Online (Sandbox Code Playgroud)
自fish2005 年首次发布以来,这些可能不是 GNU find 文档的作者在编写该文本时所考虑的 shell (而该文本或类似文本在 1994 年已经存在)并且rc最初不是 Unix shell。
有一些传言说csh(引入大括号扩展的外壳)的某些版本需要它。但是因为csh2BSD的第一个版本没有,所以很难相信那些。在 PDP11 模拟器中测试如下:
# echo find -exec {} \;
find -exec {} ;
Run Code Online (Sandbox Code Playgroud)
作为特殊情况`{',`}' 和`{}' 不受干扰地传递。
因此,如果后续版本的 csh 或 tcsh 破坏了它,我会觉得很奇怪。
它可能是为了解决某些版本中的一些错误。仍然使用 2BSD csh(在 2.79BSD、2.8BSD、2.11BSD 中也是如此):
# csh -x
# echo foo {} bar
echo foo {} bar
foo {} bar
# echo `echo foo {} bar`
echo `echo foo {} bar`
echo foo {} bar
foo bar
Run Code Online (Sandbox Code Playgroud)
引用并没有帮助:
# echo `echo foo '{}' bar`
echo `echo foo '{}' bar`
echo foo {} bar
foo bar
Run Code Online (Sandbox Code Playgroud)
您可以引用整个命令替换:
# echo "`echo foo {} bar`"
echo `echo foo {} bar`
echo foo {} bar
foo {} bar
Run Code Online (Sandbox Code Playgroud)
但这将一个参数传递给外部回声。
在cshor 中tcsh,您需要引用{}when not in its own like in:
find . -name '*.txt' -type f -exec cp {} '{}.back' \;
Run Code Online (Sandbox Code Playgroud)
(尽管这种find用法不可移植,因为某些finds 仅{}在其自身时才扩展)。
总之,csh。 bash和其他现代 shell 认识到用户可能并不要求空大括号扩展。(现代csh实际上并且现在tcsh也可能可以理智地处理。){}