Files – Compare Two Folders for Missing Files

filenamesfiles

I have two different folders each with the same file names in it but one has missing files. How am I able to compare the two folders Folder1 and Folder2 and list the files missing in Folder2 which Folder1 contains.

Best Answer

$ tree
.
|-- dir1
|   |-- file1
|   |-- file2
|   |-- file3
|   |-- file4
|   `-- file5
`-- dir2
    |-- file2
    |-- file4
    `-- file5

2 directories, 8 files
$ for f1 in dir1/*; do f2="dir2/${f1#dir1/}"; [ ! -e "$f2" ] && printf '%s\n' "$f2"; done
dir2/file1
dir2/file3

This loops through all the names in the first directory, and for each creates the corresponding name of a file expected to exist in the second directory. If that file does not exist, its name is printed.

The loop, written out more verbosely (and using basename rather than a parameter substitution to delete the directory name from the pathname of the files in the first directory):

for f1 in dir1/*; do
    f2="dir2/$( basename "$f1" )"
    if [ ! -e "$f2" ]; then
        printf '%s\n' "$f2"
    fi
done

If the files in the two directories not only have the same names, but also the same contents, you may use diff (note: BSD diff used here, GNU diff may possibly say something else):

$ diff dir1 dir2
Only in dir1: file1
Only in dir1: file3

If the file contents of files with identical names differ, then this would obviously output quite a lot of additional data that may not be of interest. diff -q may quiet it down a bit in that case.

See also the diff manual on your system.


For comparing deeper hierarchies, you may want to use rsync:

$ rsync -r --ignore-existing -i -n dir1/ dir2
>f+++++++++ file1
>f+++++++++ file3

The above will output a line for each file anywhere under dir1 that does not have a corresponding file under dir2. The -n option (--dry-run) makes sure that no file is actually transferred to dir2.

The -r option (--recursive) makes the operation recursive and -i (--itemize-changes) selects the particular output format (the >f and the pluses indicates that the file is a new file on the receiving end).

See also the rsync manual.

Related Question