You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何使用Bash递归批量重命名文件 替换路径中所有匹配字符串

Bash递归全局重命名实现方案

两个问题的根因很明确:

  1. 遍历顺序错误:如果先处理上层目录,改名后下层路径的前缀就失效了,必须从最深层的节点开始向上处理
  2. 依赖rename的实现差异:不同发行版的rename分util-linux版和perl版,语法不统一,且默认匹配规则不灵活,完全可以用Bash内置能力替代。

可直接使用的脚本

#!/bin/bash
set -euo pipefail

# 参数校验
if [ $# -ne 3 ]; then
    echo "调用方式: $0 <目标根目录> <待替换字符串> <替换为的字符串>"
    exit 1
fi

ROOT=$1
OLD_STR=$2
NEW_STR=$3

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

# 核心:-depth 参数让find先输出目录内的所有子项,最后输出目录自身,从深到浅处理避免路径失效
find "$ROOT" -depth -name "*$OLD_STR*" | while IFS= read -r path; do
    parent=$(dirname -- "$path")
    old_name=$(basename -- "$path")
    # Bash内置全局替换语法:// 表示替换所有匹配片段,一次替换完所有出现位置
    new_name=${old_name//"$OLD_STR"/"$NEW_STR"}

    [ "$old_name" = "$new_name" ] && continue
    new_path="$parent/$new_name"

    if [ -e "$new_path" ]; then
        echo "跳过 $path:目标路径 $new_path 已存在"
        continue
    fi

    mv -v -- "$path" "$new_path"
done

关键逻辑说明

  • 解决目录改名导致路径失效:find的-depth参数会自动调整遍历顺序,所有子文件、子目录都会在其父目录之前完成重命名,处理父目录时已经不需要再访问它下面的任何内容,完全不会出现找不到路径的错误。
  • 解决单次仅替换首个匹配的问题:使用Bash原生参数扩展${var//old/new}做字符串替换,不需要依赖外部rename命令,默认就会替换目标字符串里所有匹配的片段,不需要重复执行命令,性能也更高。
  • 兼容性:不依赖任何发行版特有的命令参数,只要是Bash 3.0以上版本都能正常运行,适配绝大多数Linux、macOS环境。

使用示例

针对给出的测试目录结构,给脚本加执行权限后在当前目录执行:

chmod +x recursive_rename.sh
./recursive_rename.sh . "pattern" "expression"

执行完成后就能得到预期的重命名结果,不会抛出路径不存在的报错,所有文件名、目录名中出现的pattern不管有多少处都会被一次性替换为expression。

如果需要支持正则匹配替换,只需要把new_name=${old_name//"$OLD_STR"/"$NEW_STR"}替换为new_name=$(sed "s/$OLD_STR/$NEW_STR/g" <<< "$old_name")即可,此时传入的待匹配字符串支持标准正则语法。


内容的提问来源于stack exchange,提问作者jthulhu

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.26 23:18:48