批量将文件夹内单个视频文件重命名为文件夹同名(保留扩展名)的方法求助
批量将文件夹内单个视频文件重命名为文件夹同名(保留扩展名)的方法求助
问题分析
你遇到的两个核心问题:
- 脚本语法错误:你之前执行的
mv $file $dir/$fn. $ext里,$fn.和$ext之间多了个空格,导致shell把mp4/mkv当成了独立的目标参数,而非文件名的一部分,所以mv会误以为你要把文件移动到$dir/$fn.这个目录,自然报错「target 'mp4' is not a directory」。 - 特殊字符未转义:文件夹和文件名里的空格、括号会被shell拆分,不加引号包裹变量的话,会导致路径解析混乱。
解决方案一:修正后的bash循环(稳妥兼容特殊字符)
直接修改你原来的脚本,修复语法问题并给变量加双引号,就能完美处理带空格、括号的路径:
for ext in mp4 avi mkv; do find /home/username/Videos -name "*.$ext" -print0 | while IFS= read -r -d '' file; do dir=$(dirname "$file") fn=$(basename "$dir") mv -v "$file" "$dir/$fn.$ext" done done
改动的原因:
- 用
find ... -print0配合read -d '',可以安全处理包含空格、换行、特殊字符的文件名,避免shell错误拆分 - 所有变量用双引号包裹,防止空格、括号被误解析
- 去掉了
$fn.和$ext之间的空格,正确拼接成「文件夹名.扩展名」的格式 -v参数让mv输出重命名的详细信息,方便你确认操作
解决方案二:用rename工具实现(更简洁)
如果你更习惯用rename,这里给你正确的正则表达式写法,直接在Videos目录下执行即可:
rename -v 's|^(.+/)([^/]+)/.*(\.[a-zA-Z0-9]+)$|$1$2/$2$3|' /home/username/Videos/*/*
正则逻辑解释:
^(.+/)([^/]+)/:捕获文件夹的完整路径(比如/home/username/Videos/Disneyland/)和文件夹名称(Disneyland).*(\.[a-zA-Z0-9]+)$:匹配原文件名,捕获扩展名(比如.mkv)- 替换为
$1$2/$2$3,最终生成「文件夹路径/文件夹名.扩展名」的正确格式
测试建议
批量操作前一定要先做测试,避免误改:
- 用
-n参数让rename只输出拟执行的操作,不实际修改:
rename -n 's|^(.+/)([^/]+)/.*(\.[a-zA-Z0-9]+)$|$1$2/$2$3|' /home/username/Videos/*/*
- 或者先在你创建的测试文件夹(Disneyland、The Family Video (2020))里单独验证:
cd /home/username/Videos for ext in mp4 mkv; do find ./Disneyland ./The\ Family\ Video\ \(2020\) -name "*.$ext" -print0 | while IFS= read -r -d '' file; do dir=$(dirname "$file") fn=$(basename "$dir") mv -v "$file" "$dir/$fn.$ext" done done
备注:内容来源于stack exchange,提问作者Monty Jared
相关产品推荐
相关产品推荐

