Har*_*rry 3 bash interactive find
以下命令在终端中以交互方式按预期工作.
$ find . -name '*.foo' -o -name '*.bar'
./a.foo
./b.bar
$
Run Code Online (Sandbox Code Playgroud)
但是,如果我这样做,我就没有结果!
$ ftypes="-name '*.foo' -o -name '*.bar'"
$ echo $ftypes
-name '*.foo' -o -name '*.bar'
$ find . $ftypes
$
Run Code Online (Sandbox Code Playgroud)
我的理解是,在有机会跑之前,它$ftypes会被扩展.在这种情况下,该方法也应该有效.bashfindftypes
这里发生了什么?
提前谢谢了.
PS:我需要动态构建一个文件类型列表(ftypes上面的变量),以便find稍后在脚本中给出.
到目前为止,这两个答案都建议使用eval,但是它因引起错误而享有当之无愧的声誉.以下是您可以通过以下方式获得的奇怪行为示例:
$ touch a.foo b.bar "'wibble.foo'"
$ ftypes="-name '*.foo' -o -name '*.bar'"
$ eval find . $ftypes
./b.bar
Run Code Online (Sandbox Code Playgroud)
为什么没找到文件./a.foo?这是因为该eval命令的确切解析方式.bash的解析就是这样的(省略了一些不相关的步骤):
'*.foo'并'*.bar'注意它没有解析引号,因此它只是将它们视为要匹配的文件名的一部分 - 并找到'wibble.foo'并替换它'*.foo').在此之后命令是粗略的eval find . -name "'wibble.foo'" -o "'*.bar'".顺便说一句,如果它找到了多个匹配项,那么到最后它们会变得更加愚蠢.eval,并在该行的其余部分上运行整个解析过程.find,传递参数"."," - name","wibble.foo"," - o"," - name"和"*.bar".find找到一个匹配"*.bar",但不匹配"wibble.foo".它甚至都不知道你想要它寻找"*.foo".那么你能做些什么呢?好吧,在这种特殊情况下,添加策略性双引号(eval "find . $ftypes")可以防止虚假的通配符替换,但一般情况下最好eval完全避免.当您需要构建命令时,数组是一种更好的方法(有关更多讨论,请参阅BashFAQ#050):
$ ftypes=(-name '*.foo' -o -name '*.bar')
$ find . "${ftypes[@]}"
./a.foo
./b.bar
Run Code Online (Sandbox Code Playgroud)
请注意,您也可以逐位构建选项:
$ ftypes=(-name '*.foo')
$ ftypes+=(-o -name '*.bar')
$ ftypes+=(-o -name '*.baz')
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
373 次 |
| 最近记录: |