我在目录树中有数千个文件,文件名如下:
/Folder 0001 - 0500/0001 - Portrait - House.jpg
/Folder 2500 - 3000/2505 - Landscape - Mountain.jpg
使用linux命令行我想删除文件名中第一个单词的所有内容,因此" 0001 - "和" 2500 - "。新文件名看起来像:
/Folder 0001 - 0500/Portrait - House.jpg
/Folder 2500 - 3000/Landscape - Mountain.jpg
我修改了一个有效的脚本:
find . -type f -name "*-*" -exec bash -c 'f="$1"; g="${f/[[:digit:]]/ -/ /}"; echo mv -- "$f" "$g"' _ '{}' \;
这里的问题是它会阻塞部分路径而不是文件名,因此实际输出会生成如下文件名:
/Folder -/ /001 - 0500/0001 - Portrait - House.jpg
/Folder -/ /500 - 3000/2505 - Landscape - Mountain.jpg
如何修改此脚本以使用我描述的模式重命名文件?
答案 0 :(得分:2)
find . -mindepth 2 -type f -name "*-*" -exec bash -c '
shopt -s extglob
for arg do
dir=${arg%/*}
basename_old=${arg##*/}
basename_new=${basename_old##+([[:digit:]]) - }
[[ "$basename_new" = "$basename_old" ]] && continue # skip when no rename needed
printf "%q " mv -- "$dir/$basename_old" "$dir/$basename_new"
printf "\n"
done
' _ {} +
看到此代码
${arg%/*}
删除/
中变量的最后arg
后的所有内容 - 从而删除文件名,当路径 时删除目录至少一个目录段(提供此保证是-mindepth 2
)的原因。${arg##*/}
从头开始删除与*/
最长的匹配项 - 从而删除目录,保留基本文件名。extglob
shell option,我们在fnmatch / glob风格的表达式中获得类似regex的功能,包括匹配单个数字中的一个或多个的能力;这就是为什么+([[:digit:]]) -
评估为"一个或多个数字,然后是-
"。printf '%q '
代替echo
,即使不控制文件名,也会生成安全引用的输出。-exec ... {} +
,我们将多个参数传递给每个bash
实例,而不是为找到的每个文件调用单独的解释器。使用for arg do
,我们遍历所有这些参数。