Linux 中找出两个文件的不同

本文介绍四种方法来找出两个大文件间的不同部分:利用comm命令、diff命令配合grep和awk、直接使用awk命令以及一种不推荐的grep方法。强调文件排序的重要性及各方法的注意事项。

今天遇到一个问题就是两个大文件,其中一个文件是另一个文件的子集,需要找出不同的部分,上网查询后得到如下方法:

方法一:comm命令实现

首先看看comm命令的帮助

comm --help 
Usage: comm [OPTION]... FILE1 FILE2
Compare sorted files FILE1 and FILE2 line by line.
  -1              suppress column 1 (lines unique to FILE1)
  -2              suppress column 2 (lines unique to FILE2)
  -3              suppress column 3 (lines that appear in both files)
Examples:
  comm -12 file1 file2  Print only lines present in both file1 and file2.
  comm -3 file1 file2   Print lines in file1 not in file2, and vice versa.
  -1   不显示只在第1个文件里出现过的列。
  -2   不显示只在第2个文件里出现过的列。
  -3   不显示只在第1和第2个文件里出现过的列。
  --help   在线帮助。
  --version   显示版本信息。
例子
comm - 12     就只显示在两个文件中都存在的行;
comm - 23    只显示在第一个文件中出现而未在第二个文件中出现的行;
comm - 123  则什么也不显示。

注意:两个文件比较前,一定要进行sort排序。不然输出的结果可能是错的。


方法二:使用diff命令比较

diff命令是一个比较经典的文本比较工具了,diff命令较comm的参数要多。其经常和patch命令组合使用,进行补丁升级。其默认使用的是-a参数,即逐行比较两个文件之间的不同。此处我们要实现想要得到的结果,还需要配合grep和awk实用:

diff 2.txt 1.txt |grep "<"|awk ' $1 = " " '
注意:在使用diff命令时候,也需要预先对文件进行sort排序,不然输出可能出错。


方法三:awk实现
awk应该算是shell常用命令中的泰山北斗了,几乎很多其他命令能完成的工作,awk都能完成(只不过有些写起来可能比较复杂)。本例中也不例外:
awk 'NR==FNR{a[$0]++} NR>FNR&&!a[$0]' 1.txt 2.txt

找出两个文件之间的相同部分可以使用
awk 'NR==FNR{a[$0]++} NR>FNR&&a[$0]'  1.txt 2.txt
下面的两个语句也可以换成:
awk  'NR==FNR{a[$0]}NR>FNR{ if(!($1 in a)) print $0}' file1 file2 找出文件2中不同的值
awk  'NR==FNR{a[$0]}NR>FNR{ if($1 in a)    print $0}' file1 file2 找出两文件中相同的值
注:
1、awk实现时,并不需要事先对两个文件进行sort排序,
2、注意和上两个命令中两个文件的放置顺序是不同的。三种实现方法,文件的顺序一定颠倒,颠倒了,效果就刚好想反了,就变成找出文件1中有文件2中没有的行了。


方法四:grep误人子弟法
网上另外流传一个错误的方法,即通过grep命令实现:
grep -v -f 1.txt 2.txt 经测试,无论事先是否对两个文件进行sort倒序,此方法输出的结果,发现都是不正确的。



### 使用 Vim 比较两个文本文件的差异 在 Vim 中,可以使用 `:diffsplit` 命令来比较两个文件的差异。此命令会打开两个文件,并在分割的窗口中显示它们的内容,同时高亮显示不同之处。如果在 `file1.txt` 中添加了一行文字并保存了文件,但 Vim 的对比结果没有更新,可以通过以下步骤刷新差异比较: 1. 在正常模式下,输入 `:diffupdate` 命令来刷新差异比较。 2. 确保当前窗口处于 diff 模式,如果不是,可以使用 `:set diff` 命令来启用。 这样,Vim 将重新计算两个文件的差异,并更新显示结果[^1]。 ### 使用 Java 编写程序比较两个文本文件的内容 在 Java 中,可以通过逐字节比较两个文件的方式来判断它们是否相同。以下是一个简单的示例代码,展示了如何实现这一点: ```java import java.io.*; public class FileComparator { public static boolean compareFiles(File file1, File file2) throws IOException { if (file1 == file2) { return true; } if (!file1.exists() || !file2.exists()) { return false; } if (file1.length() != file2.length()) { return false; } try (FileInputStream fis1 = new FileInputStream(file1); FileInputStream fis2 = new FileInputStream(file2)) { int byte1 = 0; int byte2 = 0; while ((byte1 = fis1.read()) != -1 && (byte2 = fis2.read()) != -1) { if (byte1 != byte2) { return false; } } } return true; } public static void main(String[] args) { File file1 = new File("path/to/file1.txt"); File file2 = new File("path/to/file2.txt"); try { if (compareFiles(file1, file2)) { System.out.println("两个文件是相同的。"); } else { System.out.println("两个文件并不相同。"); } } catch (IOException e) { e.printStackTrace(); } } } ``` 这段代码首先检查两个文件是否是同一个文件,然后检查它们是否存在以及大小是否相同。如果这些条件都满足,它会逐字节地读取两个文件并进行比较[^2]。 ### 使用 Linux 命令行工具比较两个文本文件的差异 Linux 提供了多种命令行工具来比较两个文本文件的差异,其中最常用的是 `diff` 和 `grep`。 #### 使用 `diff` 命令 `diff` 命令可以直接比较两个文件,并显示它们的不同之处。例如: ```bash diff file1.txt file2.txt ``` 此命令会输出两个文件之间的差异,包括添加、删除和修改的行。 #### 使用 `grep` 命令 `grep` 命令可以用来查找一个文件中存在而另一个文件中不存在的行。例如,要找出 `2.txt` 比 `1.txt` 多了什么行,可以使用以下命令: ```bash grep -vFf 1.txt 2.txt > difff.txt ``` 此命令会将 `2.txt` 中不在 `1.txt` 中的行输出到 `difff.txt` 文件中[^3]。 #### 使用 `sort` 和 `uniq` 命令 `sort` 和 `uniq` 命令可以结合起来用于计算两个文件的交集、并集和差集。 - **交集**:两个文件中都出现的行。 - **并集**:两个文件中的所有行加起来,去掉重复。 - **差集**:在一个文件中存在,而在另一个文件中不存在。 例如,要找出两个文件的交集,可以使用以下命令: ```bash sort a.txt b.txt | uniq -d ``` 要找出两个文件的并集,可以使用以下命令: ```bash sort a.txt b.txt | uniq ``` 要找出 `a.txt` 中存在而 `b.txt` 中不存在的行,可以使用以下命令: ```bash sort a.txt b.txt b.txt | uniq -u ``` 要找出 `b.txt` 中存在而 `a.txt` 中不存在的行,可以使用以下命令: ```bash sort b.txt a.txt a.txt | uniq -u ``` 这些命令通过排序和去重来计算两个文件不同集合[^3]。 ### 使用 `rsync` 比较两个目录的不同Linux 下,`rsync` 命令可以用于快速比较两个目录的不同。此命令不仅可以比较普通文件和目录,还可以处理软链接、块设备等特殊文件。例如,要比较两个目录的不同,可以使用以下命令: ```bash rsync -av --dry-run /path/to/dir1/ /path/to/dir2/ ``` 此命令会列出 `dir1` 和 `dir2` 之间的差异,但不会进行实际的文件传输。`-a` 选项表示归档模式,`-v` 选项表示详细输出,`--dry-run` 选项表示模拟运行,不进行实际操作。 请注意,如果有软链接,且加了对应选项(如 `-l` 或 `-a`),则可能会出现 `fileA-->fileB` 的输出[^4]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值