如何用awk依据匹配文件列批量重命名目录下的txt文件?
批量重命名txt文件的正确awk实现
正确命令
ls *.txt | awk 'NR==FNR {map[$2]=$1; next} { split($0, fn_parts, /\.txt$/) base_name = fn_parts[1] split(base_name, name_segs, /_/) match_prefix = name_segs[1]"_"name_segs[2] if (match_prefix in map) { new_name = map[match_prefix]"_"name_segs[3]".txt" print "mv", $0, new_name } }' file -
执行效果
运行后会输出符合预期的重命名命令:
mv 123_1_000.txt aaa_000.txt mv 456_2_101.txt bbb_101.txt mv 789_3_200.txt ccc_200.txt
确认输出无误后,可在命令末尾追加| sh直接执行重命名操作。
命令逻辑说明
- 构建匹配映射:
NR==FNR用于处理第一个输入文件(即匹配文件file),将文件第二列(如123_1)作为键,第一列(如aaa)作为值存入关联数组map,next跳过后续逻辑,继续处理匹配文件的下一行。
- 处理txt文件名:
- 读取
ls *.txt输出的每个文件名,用split拆分出.txt后缀前的基础文件名(如123_1_000)。 - 将基础文件名按下划线拆分,拼接出需要匹配的前缀(如
123_1)。 - 检查该前缀是否存在于映射中,若存在则生成新文件名(映射值+下划线+原文件名第三段+
.txt),最后打印mv命令。
- 读取
原命令的问题
- 输入顺序错误:原命令将匹配文件
file放在最后,导致awk先处理ls的输出,再处理匹配文件,逻辑完全颠倒。 - 变量传递错误:
-vvar=$2中的$2是shell环境变量(而非awk变量),实际为空,导致sub替换操作无效。 - 文件名处理逻辑缺失:原命令未提取txt文件名中需要匹配的前缀部分,也未保留原文件名的后缀段(如
000),完全不符合需求。
内容的提问来源于stack exchange,提问作者justaguy
相关产品推荐
相关产品推荐

