Shell command to find lines common in two files

Viewed 185606

I'm sure I once found a shell command which could print the common lines from two or more files. What is its name?

It was much simpler than diff.

12 Answers

The command you are seeking is comm. eg:-

comm -12 1.sorted.txt 2.sorted.txt

Here:

-1 : suppress column 1 (lines unique to 1.sorted.txt)

-2 : suppress column 2 (lines unique to 2.sorted.txt)

Maybe you mean comm ?

Compare sorted files FILE1 and FILE2 line by line.

With no options, produce three-column output. Column one contains lines unique to FILE1, column two contains lines unique to FILE2, and column three contains lines common to both files.

The secret in finding these information are the info pages. For GNU programs, they are much more detailed than their man-pages. Try info coreutils and it will list you all the small useful utils.

For how to do this for multiple files, see the linked answer to Finding matching lines across many files.


Combining these two answers (answer 1 and answer 2), I think you can get the result you are needing without sorting the files:

#!/bin/bash
ans="matching_lines"

for file1 in *
do 
    for file2 in *
        do 
            if  [ "$file1" != "$ans" ] && [ "$file2" != "$ans" ] && [ "$file1" != "$file2" ] ; then
                echo "Comparing: $file1 $file2 ..." >> $ans
                perl -ne 'print if ($seen{$_} .= @ARGV) =~ /10$/' $file1 $file2 >> $ans
            fi
         done 
done

Simply save it, give it execution rights (chmod +x compareFiles.sh) and run it. It will take all the files present in the current working directory and will make an all-vs-all comparison leaving in the "matching_lines" file the result.

Things to be improved:

  • Skip directories
  • Avoid comparing all the files two times (file1 vs file2 and file2 vs file1).
  • Maybe add the line number next to the matching string

Not exactly what you were asking, but something I think still may be useful to cover a slightly different scenario

If you just want to quickly have certainty of whether there is any repeated line between a bunch of files, you can use this quick solution:

cat a_bunch_of_files* | sort | uniq | wc

If the number of lines you get is less than the one you get from

cat a_bunch_of_files* | wc

then there is some repeated line.

Related