首页/系统/Linux 运维命令速查/comm 比较两个有序文件的异同
文本处理77 条

comm 比较两个有序文件的异同

输出三列:只在文件1、只在文件2、两边都有;-12 取交集、-23 取仅 1 独有,集合运算非常好用;前提是输入必须已排序。

Linux 运维命令速查系统更新于 2026-10-13

comm 是什么

comm 是 coreutils 里的集合比较工具,逐行比较两个已排序文件并输出三列:只在文件一出现的行、只在文件二出现的行、两边都有的行。用 -1、-2、-3 抑制对应列,就能分别得到交集与两个方向的差集。它的杀手场景是清单比对:两台机器的软件包名、两个环境的配置项、迁移前后的文件列表、依赖白名单校验,都是一条命令出结果。前提是输入必须按相同排序规则排好序,否则输出没有意义。

基本信息

适用平台GNU/Linux、macOS(BSD 与 GNU 行为基本一致)
语法comm [选项] 文件1 文件2
前置要求两个文件都必须已按相同排序规则排序
列含义第一列 仅文件1;第二列 仅文件2;第三列 两者共有
常用选项-1 -2 -3 抑制对应列,可任意组合
分隔符列之间用制表符分隔

典型使用场景

  • 比对两台服务器安装的软件包清单,找出只在一台存在的包。
  • 核对两个环境的配置键是否一致,上线前发现遗漏项。
  • 检查备份清单与源目录文件清单的差集,确认有没有漏备文件。
  • 比对两个版本导出的域名或 IP 列表,做迁移前后的一致性核对。
  • 在流水线里做白名单校验:把实际使用的依赖与允许列表求差集,非空即告警。

常用写法

常用写法
LC_ALL=C sort -u a.txt > a.sorted   # 统一排序规则并去重
LC_ALL=C sort -u b.txt > b.sorted
comm a.sorted b.sorted              # 三列全看:两边独有 + 共有
comm -12 a.sorted b.sorted          # 只看共有(两文件的交集)
comm -23 a.sorted b.sorted          # 只在 a 中(a 独有的差集)
comm -13 a.sorted b.sorted          # 只在 b 中
comm -3 a.sorted b.sorted | sed 's/^[[:blank:]]*//'   # 去掉列缩进后输出
comm -12 <(sort -u x.txt) <(sort -u y.txt)            # 进程替换,免落盘

抑制列组合读法

用法含义典型用途
默认不抑制三列全输出人工核对完整差异
-12隐藏前两列只看交集
-23隐藏第二三列只看文件1 独有的行
-13隐藏第一三列只看文件2 独有的行
-3隐藏第三列只看两边各自独有的差异
-123全部隐藏无输出即两文件内容完全相同
排序规则必须完全一致:一边用 LC_ALL=C、另一边用中文 locale,或一边 sort -n 一边默认字典序,比较结果都会错。做集合比较时统一在两侧都加 LC_ALL=C,这是最省心的做法。
输入未排序时 GNU comm 只打印一行 not in sorted order 的提示然后照常输出,很容易被当成真实差异;稳妥流程是先各自 sort -u 落盘,再比对。
comm 的输出列用制表符分隔,想抑制列就用 -1/-2/-3,不要用 cut 硬切——切列会因制表符被替换成空格而错位。

易错点

  • 输入未排序就比对,GNU comm 只给一行警告后继续输出,三列毫无规律却看似有效,极易被当成真实差异上报;比对前先 sort -u 落盘。
  • 两侧排序规则不一致(C 与 UTF-8 混用)时,含大小写、中文的行顺序不同,差异列会凭空多出大量噪音;跨机比对统一加 LC_ALL=C。
  • 文件存在重复行时 comm 逐行匹配,交集列表会出现重复项,统计数量随之失真;比较前先 sort -u 去重。
  • 用 cut 或 awk 硬切列会因制表符与空格差异而错位,导致结果错行;列抑制只用 -1/-2/-3。
  • 对超过内存的大清单用进程替换比较会同时读入两份数据,可能触发 OOM;上亿行的清单先切分再分批 comm。

数据来源与参考

  • man 1 comm(GNU coreutils 手册)

相关工具

​‌‌​​‌​​​‌‌​‌‌‌‌​‌‌​​​‌‌​‌‌‌​​‌‌​​‌​‌‌‌​​‌‌‌​​​‌​‌‌​‌​​‌​‌‌‌​​​‌​‌‌​‌​​‌​‌‌​​​‌‌​‌‌‌​‌​​​‌‌​‌‌‌‌​​‌​‌‌‌​​‌‌​​​‌‌​‌‌​‌‌‌‌​‌‌​‌‌​‌