怎么写 Shell 脚本批量修改文件后缀名为 bak?

文章导读
先说结论:批量改后缀属于高风险操作,建议优先编写完整脚本以便控制逻辑,或在终端使用 find 命令配合 -i 参数预览。
📋 目录
  1. A 完整脚本示例
  2. B 命令行快速执行
  3. C 验证方法
  4. D 常见风险与注意事项
A A

先说结论:批量改后缀属于高风险操作,建议优先编写完整脚本以便控制逻辑,或在终端使用 find 命令配合 -i 参数预览。

  • 适合:需要为配置文件或代码文件建立备份副本的场景
  • 先看:当前系统安装的 rename 命令版本,不同发行版行为不一致
  • 建议:优先使用 find + mv 组合,兼容性比 rename 命令更好

标题虽为“写脚本”,但在简单场景下直接使用终端命令更高效。若需复用或复杂逻辑,请参考下方的完整脚本示例。

完整脚本示例

以下脚本支持参数化配置,包含错误处理和覆盖检查,保存为 change_ext.sh 后赋予执行权限。

#!/bin/bash
set -euo pipefail

# 用法:./change_ext.sh <旧后缀> <新后缀> [目录]
OLD_EXT=${1:-".txt"}
NEW_EXT=${2:-".bak"}
TARGET_DIR=${3:-"."}

if [ ! -d "$TARGET_DIR" ]; then
    echo "错误:目录 $TARGET_DIR 不存在"
    exit 1
fi

echo "开始在 $TARGET_DIR 中将 $OLD_EXT 修改为 $NEW_EXT..."

find "$TARGET_DIR" -maxdepth 1 -type f -name "*$OLD_EXT" | while read -r file; do
    target="${file%$OLD_EXT}$NEW_EXT"
    if [ -e "$target" ]; then
        echo "跳过:$target 已存在,避免覆盖"
        continue
    fi
    mv "$file" "$target" && echo "成功:$file -> $target"
done

echo "操作完成"

命令行快速执行

若只需在当前目录执行,可使用以下命令。注意命令中使用了 _ 占位符传递参数,并添加了 -n 防止覆盖(GNU 核心工具)。

怎么写 Shell 脚本批量修改文件后缀名为 bak?
find . -maxdepth 1 -type f -name "*.txt" -exec sh -c 'mv -n "$1" "${1%.txt}.bak"' _ {} \;

如果需要交互式确认(更安全),将 -n 改为 -i:

find . -maxdepth 1 -type f -name "*.txt" -exec sh -c 'mv -i "$1" "${1%.txt}.bak"' _ {} \;

验证方法

执行完成后,通过以下命令确认旧文件已消失且新文件存在:

find . -maxdepth 1 -type f -name "*.txt"
find . -maxdepth 1 -type f -name "*.bak"

常见风险与注意事项

  • 参数传递陷阱:find -exec sh -c 中,{} 对应的是 $1 而不是 $0,$0 是脚本名,需用 _ 占位。
  • 覆盖风险:mv 默认会静默覆盖目标文件,务必使用 -n 参数或在脚本中检查文件是否存在。
  • 递归风险:不加 -maxdepth 会修改子目录文件,可能误伤依赖特定后缀的程序。
  • rename 版本差异:Ubuntu 默认 Perl 版本,CentOS 可能是 util-linux 版本,参数完全不同,生产环境慎用。