Linux Bash中如何对比两个文本文件的文件名并忽略指定后缀
解决Linux Bash对比文件列表并忽略指定后缀的问题
需求说明
现有两个列表文件list1.txt和list2.txt,每行存储一个文件名。需通过Linux Bash原生命令生成result.txt,要求包含仅存在于list2.txt、不存在于list1.txt中的文件名,且忽略指定后缀:.x、.xy、.yx、.y、.jpg。注意:文件名可包含点号,并非所有文件名都有后缀。
示例文件内容
list1.txt
text.x example.xy file.yx data.y edit edit.jpg
list2.txt
text rainbow.z file data.y sunshine edit.test.jpg edit.random
预期result.txt
rainbow.z sunshine edit.test.jpg edit.random
你的脚本问题分析
你提供的脚本存在多处逻辑和语法错误:
sed -i用于修改文件,而非处理变量内容,此处用法完全错误;- 缺少
if判断语句,then和fi无对应逻辑触发; - 未实现对比
list1.txt的核心逻辑,仅盲目处理list2.txt的行。
正确解决方案
方法一:使用awk(高效推荐)
利用awk的字典特性,一次性处理两个文件,无需临时文件:
awk ' BEGIN { # 按后缀长度从长到短定义,避免短后缀优先匹配(如.xy比.x长,先处理) suffixes[0] = "\\.xy$" suffixes[1] = "\\.yx$" suffixes[2] = "\\.jpg$" suffixes[3] = "\\.x$" suffixes[4] = "\\.y$" } # 处理list1,构建去后缀后的基准字典 NR == FNR { fname = $0 for (i in suffixes) { if (fname ~ suffixes[i]) { fname = gensub(suffixes[i], "", 1, fname) break } } base[fname] = 1 next } # 处理list2,检查是否不在基准字典中 { fname = $0 orig = fname for (i in suffixes) { if (fname ~ suffixes[i]) { fname = gensub(suffixes[i], "", 1, fname) break } } if (!(fname in base)) { print orig } }' list1.txt list2.txt > result.txt
方法二:使用Bash循环+sed+grep(直观易理解)
先处理list1生成基准列表,再逐行检查list2:
# 处理list1,生成去后缀并去重的基准文件 sed -E 's/(\.xy|\.yx|\.jpg|\.x|\.y)$//' list1.txt | sort -u > list1_processed.txt # 遍历list2的每一行,检查是否符合条件 while IFS= read -r line; do # 对当前文件名去掉指定后缀 processed=$(echo "$line" | sed -E 's/(\.xy|\.yx|\.jpg|\.x|\.y)$//') # 检查处理后的文件名是否不在基准列表中 if ! grep -Fxq "$processed" list1_processed.txt; then echo "$line" >> result.txt fi done < list2.txt # 可选:清理临时文件 rm list1_processed.txt
两种方法均符合你的需求,执行后生成的result.txt与预期一致。
内容的提问来源于stack exchange,提问作者JohnFreeman1212
相关产品推荐
相关产品推荐

