如何在Ubuntu命令行中递归查找并删除文件夹内的连续重复行
解决Ubuntu命令行递归查找并删除连续重复行的问题
看起来你之前的sed替换操作不小心搞出了一堆连续重复的行,而且尝试用grep查找的时候踩了坑——这很正常,因为grep默认是单行模式,没法直接匹配跨两行的重复内容,而且你的正则写法也没考虑到多行匹配的场景。我来帮你一步步解决:
第一步:先找出所有包含连续重复行的文件及重复内容
你需要用支持多行匹配的工具,这里推荐两种方法:
方法1:用pcregrep(需要先安装)
pcregrep支持Perl兼容正则表达式,天生支持多行匹配,非常适合这个场景:
# 先安装pcregrep(如果没装的话) sudo apt update && sudo apt install -y pcregrep # 递归查找所有连续重复的行,带颜色高亮 sudo pcregrep -rM --color '^(.*)$\n\1' .
参数解释:
-r:递归遍历子目录-M:允许正则表达式匹配多行内容^(.*)$\n\1:匹配任意一行,紧接着完全相同的另一行(\1引用前一行的内容)
方法2:用awk(无需额外安装)
如果不想装新工具,awk也能轻松实现,用find配合awk递归处理所有文件:
sudo find . -type f -exec awk 'prev == $0 {print FILENAME ": " $0} {prev = $0}' {} +
这个命令会记录每一行的上一行内容,如果当前行和上一行完全相同,就打印出文件名和重复的行内容。
第二步:删除连续重复的行(保留其中一行)
确认重复内容后,就可以批量删除连续重复的行了,同样给你两种可靠的方法:
方法1:用awk原地修改(简单直观)
这个命令会遍历每个文件,只保留连续重复行中的第一行:
sudo find . -type f -exec awk 'prev != $0 {print; prev=$0}' {} -i inplace \;
参数解释:
-i inplace:让awk直接原地修改文件(类似sed的-i)prev != $0 {print; prev=$0}:只有当前行和上一行不同时才打印,同时更新上一行的记录
方法2:用sed原地修改(适合熟悉sed的用户)
sed的多行处理命令也能实现同样效果:
sudo find . -type f -exec sed -i '/^\(.*\)$/{$!N;/^\(.*\)\n\1$/!P;D}' {} \;
参数解释:
/^\(.*\)$/:匹配任意一行$!N:如果不是文件最后一行,就读取下一行到模式空间/^\(.*\)\n\1$/!P:如果模式空间里不是两行完全相同,就打印第一行D:删除模式空间的第一部分,继续处理剩余内容
重要提醒:操作前先备份!
在批量修改文件前,一定要先备份当前目录的所有文件,避免操作失误造成更大损失:
sudo tar -czf backup_before_fix.tar.gz .
为什么你之前的grep命令会报错?
你用的grep -iRE '\(^.*$\)\1' .和grep -iRP '\(^.*$\)\1'有两个问题:
- 单行模式限制:grep默认只处理单行内容,没法匹配跨两行的重复行,所以你的正则根本找不到连续重复的内容。
- 正则写法问题:即使开启PCRE模式(
-P),你写的\(^.*$\)\1是想捕获整行然后引用,但在单行模式下,这个正则只会匹配一行里重复的内容(比如aaaa),而不是两行重复。而且在BRE模式(默认,-E是ERE)下,引用捕获组的写法也不对。
内容的提问来源于stack exchange,提问作者Jens
相关产品推荐
相关产品推荐

