如何在Bash中将目录下所有文件名的第n个字符转为大写
Bash批量将文件名指定位置字符转大写的实现方案
对应场景:需要批量处理目标目录下的文件名,将从开头计数的第n位字符转为大写。以示例效果验证:现有文件
_aaa.txt、_bbb.txt、_ccc.txt,处理后得到_aAa.txt、_bBb.txt、_cCc.txt。
注:示例中对应转换的字符位置为从0开始计数的第2位(即首个字符_为第0位、第一个字母为第1位、第二个字母为第2位)。
方案1:纯Bash内置语法实现(跨平台无依赖)
不需要安装任何外部工具,同时兼容Linux、macOS的默认Bash环境(含macOS预装的老版本Bash),对带空格、特殊字符的文件名兼容性最优。
# 可按需修改的配置项 TARGET_DIR="./" # 要处理的目标目录 TARGET_POS=2 # 需要转大写的字符位置(从0开始计数) # 遍历目录下所有普通文件 for old_path in "$TARGET_DIR"/*; do # 跳过子目录,仅处理文件 [ -f "$old_path" ] || continue # 提取纯文件名(剥离路径前缀) old_name=$(basename "$old_path") # 拆分文件名三段:目标位置前的内容、目标位置的单字符、目标位置后的内容 prefix=${old_name:0:$TARGET_POS} target_char=${old_name:$TARGET_POS:1} suffix=${old_name:$((TARGET_POS + 1))} # 将目标字符转为大写,兼容所有版本Bash upper_char=$(printf '%s' "$target_char" | tr '[:lower:]' '[:upper:]') # 拼接新文件名 new_name="${prefix}${upper_char}${suffix}" # 新旧文件名一致时跳过,避免无意义的mv操作 [ "$old_name" = "$new_name" ] && continue # 先打印预览(确认无误后删除下面的echo,启用mv命令) echo "重命名:$old_name -> $new_name" # mv "$old_path" "$TARGET_DIR/$new_name" done
验证:当配置
TARGET_POS=2时,处理_aaa.txt的拆分逻辑为:prefix=_a,target_char=a转大写为A,suffix=a.txt,最终拼接结果为_aAa.txt,完全匹配示例效果。
方案2:借助rename工具实现(大文件量场景效率更高)
根据所用系统的rename版本不同,对应不同写法,建议执行前先加预览参数确认效果:
GNU rename(Ubuntu、CentOS等默认Linux发行版自带)
通过正则匹配拆分文件名位置,直接执行转换:# 去掉-n参数可正式执行重命名,2对应目标字符位置 rename -n 's/^(.{2})(.)/$1\U$2/' ./*.txt语法说明:正则将文件名拆为「前2个字符」「第3个字符(即索引2位置)」两部分,用
\U将匹配到的单字符转为大写。macOS环境(无GNU rename时)
可通过Perl实现等价逻辑,无需安装额外工具:# 去掉末尾的| bash可先预览生成的重命名命令,2对应目标字符位置 perl -le 'for $f (<*.txt>) { $n = $f; $n =~ s/^(.{2})(.)/$1\U$2/; print "mv \"$f\" \"$n\"" unless $f eq $n }' | bash
注意事项
- 计数规则:所有方案默认从文件名第一个字符开始从0计数,如果需要从1开始计数,将位置参数减1即可。
- 操作安全:批量重命名前务必先执行预览逻辑,确认所有转换结果符合预期后,再启用实际的重命名命令,避免误操作。
- 扩展名兼容:所有方案的字符计数覆盖完整文件名(含扩展名),如果需要仅在主文件名部分计数,可先拆分主文件名和扩展名再执行转换。
内容的提问来源于stack exchange,提问作者Jane_
相关产品推荐
相关产品推荐

