当我遇到这个奇怪的问题时,我试图批量重命名并使用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`/..' _ {} \;
我的问题是为什么会发生这种情况。我一直认为回应命令的评估与运行命令完全相同。
答案 0 :(得分:4)
执行此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扩展。