find(1) 的 -exec 参数中的子 shell 参数

find(1) 的 -exec 参数中的子 shell 参数

为什么不

find . -type f -exec echo $(file={}; echo ${file:0:5}) \;

给出文件的前五个字符,如下所示:

find . -type f -exec bash -c 'echo ${1:0:5}' funcname {} \;

背景

我正在尝试将一棵树上的图像批量转换为缩略图,并且我想通过在文件名末尾但在扩展名之前添加“_thumb”来动态重命名它们。对于一个文件来说,这个重命名过程很容易:

file='I am a picture.jpg'
mv \"$file\" \"${file%\.*}_thumb.${file##*\.}\"

(第二行扩展为mv "I am a picture.jpg" "I am a picture_thumb.jpg"

但是当我尝试将此命令封装-execfind(1)我无法操作给出的文件名find(简化示例):

find . -type f -exec ${{}:0:5}) \;

给出

bash: ${{}:0:5}: bad substitution

使用子 shell 我可以得到更进一步的结果:

find . -type f -exec echo $(file={}; echo ${file:0:5}) \;

这确实回显了文件名,但由于某种原因并没有执行字符串操作。

我终于找到了解决方案这篇文章

find . -type f -exec bash -c 'echo ${1:0:5}' funcname {} \;

但我不明白当$(...)构造不起作用时为什么这会起作用。

答案1

exec按照说明操作:使用exec()。除非被告知 ( -exec bash ...),否则它不会涉及 shell,如果涉及,则仍然需要单引号来防止交互式 shell 解释变量插值。(shell 不是魔术,不知道你打算用其他东西来插值。)


例如,当您使用以下命令时:

查找 . -type f -exec echo$(文件={}; 回显 ${文件:0:5})\;

你的外壳第一的通过执行执行过程替换$(file={}; echo ${file:0:5}),它只是输出{}然后执行最终命令:

查找 . -type f -exec echo{}\;

相关内容