为什么不
find . -type f -exec echo $(file={}; echo ${file:0:5}) \;
Run Code Online (Sandbox Code Playgroud)
给出文件的前五个字符,而这有效:
find . -type f -exec bash -c 'echo ${1:0:5}' funcname {} \;
Run Code Online (Sandbox Code Playgroud)
背景:
我正在尝试将一棵充满图像的树批量转换为缩略图,并且我想通过在文件名末尾但在扩展名之前添加“_thumb”来动态重命名它们。对于一个文件,这个重命名过程很容易:
file='I am a picture.jpg'
mv \"$file\" \"${file%\.*}_thumb.${file##*\.}\"
Run Code Online (Sandbox Code Playgroud)
(第二行扩展为mv "I am a picture.jpg" "I am a picture_thumb.jpg")
但是当我尝试将此命令封装在-exec参数中时,find(1)我无法操作由find(示例简化)给出的文件名:
find . -type f -exec ${{}:0:5}) \;
Run Code Online (Sandbox Code Playgroud)
给
bash: ${{}:0:5}: bad substitution
Run Code Online (Sandbox Code Playgroud)
使用子shell我得到了进一步:
find . -type f -exec echo $(file={}; echo ${file:0:5}) \;
Run Code Online (Sandbox Code Playgroud)
这确实回显了文件名,但由于某种原因不执行字符串操作。
我终于在这篇 SO post 中找到了解决方案:
find . -type f -exec bash -c 'echo ${1:0:5}' funcname {} \;
Run Code Online (Sandbox Code Playgroud)
但我不明白为什么当$(...)构造不起作用时这会起作用。
exec做它所说的:使用exec(). 它不涉及 shell,除非它被告知 ( -exec bash ...),如果是的话,你仍然需要单引号来防止你的交互式 shell 解释变量插值。(外壳不是魔法,也不知道您打算将它们插入其他东西。)
例如,当您使用以下命令时:
找 。-type f -exec echo $(file={}; echo ${file:0:5}) \;
您的 shell首先通过执行 执行进程替换$(file={}; echo ${file:0:5}),它只是输出{},然后执行最终命令:
找 。-type f -exec echo {} \;