-> find .. -name bin -exec for file in {}/* ; do echo $file ; done \;
-bash: syntax error near unexpected token `do'
该命令的正确语法是什么?
答案1
要使用多个语句(例如 -loop for
)作为 的参数-exec
,需要bash
显式调用 shell,例如 :
find .. -name bin -exec bash -c 'for file in "$1"/* ; do echo "$file" ; done' none {} \;
即使对于包含空格或其他敌对字符的文件名,这也是安全的。
如何bash -c
运作
可以使用以下形式的命令调用 bash:
bash -c some_complex_commands arg0 arg1 arg2 ...
在这种情况下,bash 将执行 string 中的任何内容some_complex_commands
。这些命令可以使用常用的 shell位置参数。arg0
上面命令后的第一个参数被分配给$0
,第二个参数被分配给$1
,第三个参数被分配给$2
,等等。
当执行普通的 shell 脚本时,$0
是脚本的名称,也是$1
出现在命令行上的第一个参数。为了与这一传统保持一致,该bash -c
命令被编写为将文件名({}
以 find 的表示法)分配给$1
.由于该脚本没有合理的名称,因此none
被指定为占位符$0
。
答案2
看来你得到的事情与你想要的相反。尝试这个:
for f in `find .. -name bin`
do
echo $f
done
答案3
您可以使用原语来近似伪代码的输出,find
如下所示:
find .. -path \*/bin/\* ! -name .\*
...它应该只打印名称不以 .它们在某种程度上植根于父目录,并且在更大程度上植根于名为 的目录/bin
。
一般来说,我可以想到在子进程中循环的各种实际目的find -exec
,但我不认为对传递的参数执行 shelld glob 是可行的find
。要执行与伪代码相同的操作printf
- 因为它的使用可以保证参数的字面翻译为输出 - 你可能会这样做......
find .. -type d -name bin -exec sh -c '
printf %s\\n "$0/"*' {} \;
...它可以在没有循环的情况下进行打印和通配符for
。不过,此命令与示例命令之间的一个区别是,如果没有与-type d
名称匹配的结果的规范和类型,则结果bin
将是echo
d - 因此您很可能会看到很多内容bin/*
被写入标准输出。当然,即使 w/ -type d
,也不能保证会*
解析 - 空目录或仅包含.
文件的目录不会呈现任何匹配项,因此您可能会看到它。
另请注意,示例伪代码,因为它使用{} \;
原语可能比其他方法慢很多。我们将printf
再次尝试该操作,例如:
find .. -type d -name bin -exec sh -c '
for d do printf %s\\n "$d/"*; done' -- {} +
...这仍然存在空 glob 情况的风险,但-exec
它不是每次匹配一个 shell,而是收集尽可能多的参数,因为它可以在执行时合理地传递给另一个进程,并将参数传递到其位置参数数组sh
中"$@"
- 我们可以循环使用for d do printf...
.
现在,如果您想做的不仅仅是打印结果(这是我通常认为在语句中循环有用的事情)之外的其他事情-exec
,您可以回退到前面的-path
示例并将其与-exec
类似的组合...
find .. -path \*/bin/\* -exec sh -c '
for arg do : something with "$arg"
done' -- {} +