【问题标题】:Unexpected behavior when using eval in "find -exec"在“find -exec”中使用 eval 时出现意外行为
【发布时间】:2017-07-23 10:18:14
【问题描述】:

当我遇到这个奇怪的问题时,我正在尝试使用 bash 批量重命名和移动文件夹中的一些文件。

我试图将每个 PNG 文件在文件层次结构中向上移动一个目录。首先我跑了:

find . -name *png -exec echo {} \;

一切都按预期进行:

./res/drawable-xxxhdpi/ic_pickonmap.png
./res/drawable-hdpi/ic_pickonmap.png
./res/drawable-mdpi/ic_pickonmap.png
./res/drawable-xxhdpi/ic_pickonmap.png
./res/drawable-xhdpi/ic_pickonmap.png

然后我运行以下命令:

find . -name *png -exec dirname {} \;

按预期打印:

./res/drawable-xxxhdpi
./res/drawable-hdpi
./res/drawable-mdpi
./res/drawable-xxhdpi
./res/drawable-xhdpi

但是当我简单地回显 dirname 的评估时,它的行为非常奇怪。当我执行时:

find . -name *png -exec echo `dirname {}` \;

它只打印点

[blackvvine@unweeded-garden icon.bac]$ find . -name *png -exec echo `dirname {}` \;
.
.
.
.
.

解决移动文件的问题不是我的本意。我最终解决了它:

find . -name *.png -exec bash -c 'mv $1 `dirname $1`/..' _ {} \;

我的问题是为什么会发生这种情况。我一直认为回显命令的评估与运行它是完全等价的。

【问题讨论】:

  • 原来的问题可能用-execdir mv {} .. \;解决得更优雅
  • find . -name *png -exec echo {} \;,如果它的行为如您所说,则根本不像预期的那样行为。我希望它会出现类似ic_pickonmap.png: unknown primary or operator 的错误。你得到的行为是我对find . -name '*png' 的期望

标签: linux bash shell unix find


【解决方案1】:

当你执行这个find 命令时:

find . -name '*.png' -exec echo `dirname {}` \;

它有效地执行了这个命令:

find . -name '*.png' -exec echo . \;

这是因为命令替换,即被反引号`...`包围的部分,发生在find命令执行之前,而{}被单个点替换。

您可以通过运行bash -cx 来验证这一点(调试已打开):

bash -cx 'find . -name "*.png" -exec echo $(dirname {}) \;'
++ dirname '{}'
+ find . -name '*.png' -exec echo . ';'
.
.

可以看到先执行dirname '{}',然后处理find结果。


顺便说一句,如果您从当前目录运行find,这是将文件移动到父目录的更好命令:

find . -name '*.png' -execdir mv {} .. \;

注意*.png应该被引用,否则在find命令执行之前它会被shell扩展。

【讨论】:

  • @anubhava 就是这样,它们不会产生相同的输出。另外,我不确定我是否正确地遵循了您的解释,但 PNG 文件不在 CWD 中,因此它们的 dirname 不应该是 .
猜你喜欢
  • 2016-10-22
  • 1970-01-01
  • 1970-01-01
  • 2011-05-08
  • 2017-05-28
  • 1970-01-01
  • 2018-02-13
  • 1970-01-01
  • 2021-09-28
相关资源
最近更新 更多