在 find exec 中使用 for 循环

在 find exec 中使用 for 循环
 -> 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将是echod - 因此您很可能会看到很多内容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' -- {} +

相关内容