首页/系统/Linux 运维命令速查/场景:批量重命名文件(循环 + mv)
文件与目录76 条

场景:批量重命名文件(循环 + mv)

把 *.jpeg 全改成 *.jpg 这类批量改名:shell 循环 + 参数扩展是通用公式,动手前先 echo 干跑。

Linux 运维命令速查系统更新于 2026-10-13

批量改名的通用公式

Linux 上没有统一的批量改名命令,通用做法是「通配符取文件 → for 循环 → mv → 参数扩展拼新名字」,或者用 rename 这类专用工具。这类操作的风险集中在三处:文件名里的空格与特殊字符、目标名与已有文件撞名、以及干跑与执行不是同一条命令导致结果和预期不一致。

基本信息

适用平台Linux/Unix(bash 或兼容 shell)
通用写法for f in 通配符; do mv 原 新; done
参数扩展${f%.jpeg} 去掉后缀,${f##*/} 取文件名,${f%%.*} 去掉最长的后缀
专用工具rename,注意存在 Perl 版与 util-linux 版两种不兼容实现
纪律先 echo 干跑打印将要执行的动作,确认无误后再把 echo 去掉

典型使用场景

  • 统一扩展名:把 *.jpeg 全改成 *.jpg
  • 批量加前缀或后缀:给导出的报表统一加日期
  • 去掉下载文件名里的多余后缀(.txt.1 这类重复后缀)
  • 按规则编号:给一批图片加上序号前缀
  • 递归改名:目录树里所有匹配文件统一调整,配合 find 处理

循环版:先干跑再执行

循环版:先干跑再执行
for f in *.jpeg; do echo mv -- "$f" "${f%.jpeg}.jpg"; done   # 干跑:只打印
for f in *.jpeg; do mv -- "$f" "${f%.jpeg}.jpg"; done          # 确认后再执行
for f in *.txt;  do mv -- "$f" "archived-$f"; done              # 加前缀
for f in *; do echo "$f" "${f%%.*}"; done                       # 先看参数扩展结果

rename 版:先分清实现

rename 版:先分清实现
rename 's/[.]jpeg$/.jpg/' *.jpeg     # Perl 版:sed 风格表达式
rename -n 's/[.]jpeg$/.jpg/' *.jpeg   # Perl 版的干跑
rename .jpeg .jpg *.jpeg              # util-linux 版:纯字符串替换
rename --version                      # 先确认装的是哪一个

递归与特殊文件名

递归与特殊文件名
find . -type f -name '*.jpeg' -print0 | while IFS= read -r -d '' f; do
  echo mv -- "$f" "${f%.jpeg}.jpg"    # 用 -print0 与 -d '' 兼容空格与换行
 done

改名写法对比

写法适用场景风险点
for + mv当前目录、文件名规律变量不加引号会被拆词
参数扩展拼接后缀与前缀写成 ${f%%...} 会多吃一段
Perl 版 rename正则替换、条件改名语法与 util-linux 版完全不同
util-linux 版 rename简单字符串替换只做字面替换,没有正则能力
find -print0递归、文件名含空格必须配 read -d '' 或 xargs -0
参数扩展是这条公式的核心:${f%.jpeg} 从右边去掉最短匹配的 .jpeg,${f%%.jpeg} 去掉最长匹配,${f##*/} 取出文件名部分。先单独跑一遍 echo 看扩展结果,比在 mv 里试错安全得多。
rename 有两个同名不同实现的版本:Perl 版接受 sed 风格表达式(s/a/b/),util-linux 版只做字面替换。在别人的机器上直接抄命令很容易报错或改错名字,先跑 rename --version 确认,再用干跑选项预览。
给一批文件加序号时用 printf 做零填充,能让 ls 与排序保持自然顺序,避免 10 排在 2 前面:先 for f in *.jpg 循环取文件,计数器初始化为 i=1 并逐次递增,目标名写成 $(printf '%03d' $i)-$f。加工号或日期前缀时同理,长度固定才能排序正确。

易错点

  • 循环里变量不加引号会被按空格拆词,文件名含空格必然出错,引号是纪律不是风格
  • mv 的目标名与已有文件撞名会直接覆盖,重要操作前先干跑并把清单存档
  • 参数扩展里 % 与 %% 的含义不同,写错会把文件名吃掉一截,改名前先 echo 验证
  • Perl 版 rename 与 util-linux 版 rename 语法不兼容,跨机器执行前必须确认版本
  • 递归改名时若通配符命中备份文件或子目录,会连不该动的文件一起改,先用 find 打印清单核对

数据来源与参考

  • man 1 bash(参数扩展)
  • man 1 mv(GNU coreutils 手册)

相关工具

​‌‌​​‌​​​‌‌​‌‌‌‌​‌‌​​​‌‌​‌‌‌​​‌‌​​‌​‌‌‌​​‌‌‌​​​‌​‌‌​‌​​‌​‌‌‌​​​‌​‌‌​‌​​‌​‌‌​​​‌‌​‌‌‌​‌​​​‌‌​‌‌‌‌​​‌​‌‌‌​​‌‌​​​‌‌​‌‌​‌‌‌‌​‌‌​‌‌​‌