如何在 bash 中找到多个文件的 "full symmetric difference"?

How do I find the "full symmetric difference" of several files in bash?

我有五个文件,每个文件都列出了完整的文件路径,如下所示:

File one
    /full/file/path/one.xlsx
    /full/file/path/two.txt
    /full/file/path/three.pdf
    ....
File two
    /a/b/c/d/r.txt
    /full/file/path/two.txt
    ....
File three
    /obe/two/three/graph.m
    /full/file/path/two.txt
    ....
File four
    .....
File five
     .....

所有五个可能包含完全相同的完整文件路径。但是,我想过滤掉每个文件共有的路径。换句话说,我希望删除所有文件的总交集。下面是一个视觉辅助工具,用三个文件的较小示例描述了我想要的内容(请原谅我糟糕的鼠标绘图技巧):

symmetric difference 上的页面没有准确描述我想要的内容,因此视觉辅助和短语完全对称差异周围的引号。

问题

如何过滤多个文件中的文本行以获得我想要的上述情况?

假设每个文件都没有重复项,您可以

  • 连接所有文件(cat file1 file2 ... file5
  • 计算每行出现的频率 (sort | uniq -c)
  • 并且只保留出现次数少于五次的行(sed -En 's/^ *[1-4] //p')

sort file1 ... file5 | uniq -c | sed -En 's/^ *[1-4] //p'

但是,如果某个文件可能多次包含同一行,则您必须先删除这些重复项。

f() { sort -u ""; }
sort <(f file1) ... <(f file5) | uniq -c | sed -En 's/^ *[1-4] //p'

或(有点慢但更容易编辑)

for i in file1 ... file5; do sort -u "$i"; done |
sort | uniq -c | sed -En 's/^ *[1-4] //p'

如果出于某种原因你想保留单个文件的重复项并且还想保留行的原始顺序,那么你可以反转上面的命令以仅打印出现在每个文件中的行并使用 grep:

f() { sort -u ""; }
grep -Fxvhf <(sort <(f file1) ... <(f file5) |
              uniq -c | sed -En 's/^ *5 //p') file1 ... file5

或(有点慢但更容易编辑)

files=(file1 ... file5)
grep -Fxvhf <(for i in "${files[@]}"; do sort -u "$i"; done |
              sort | uniq -c | sed -En 's/^ *5 //p') "${files[@]}"