I have two directories on two different hard drives and want to check if the content is really exactly the same. From what I read I can use diff -rq dir1 dir2 to check if files are missing or differ.

report only when files differ

recursively compare any subdirectories found

However as far as I see diff does not check if the permissions or timestamps differ. Is there another parameter for diff or other tool where it is possible to check that as well?


2 Answers 2


mtree(8) is an excellent tool for this:

The command:

$ mtree -cp path/on/hostA -K sha256 | ssh hostB mtree -p path/on/hostB

will report differences between the heirarchy in hostA:path/on/hostA and the heirarchy in hostB:path/on/hostB in terms of type, size, timestamp, permissions, and content. Additionally, missing entries (not found on hostB) or extraneous entries (found only on hostB) are reported.

If the heirarcies are identical, mtree will issue no output and return an exit code of 0:

$ mtree -cp path/on/hostA -K sha256 | ssh hostB mtree -p path/on/hostB && echo match

Otherwise, mtree will return a non-zero exit code, and itemize the entries that differ:

# create some differences on hostB:

$ ssh hostB 'rmdir path/on/hostB/d'
$ ssh hostB 'mkdir path/on/hostB/e'
$ ssh hostB 'date > path/on/hostB/b/B'
$ ssh hostB 'touch path/on/hostB/b/BB'
$ ssh hostB 'chmod 644 path/on/hostB/c/C'

# and then compare:

$ mtree -cp path/on/hostA -K sha256 | ssh hostB mtree -p path/on/hostB || echo fail
.:      modification time (Tue May 18 13:27:20 2021, Tue May 18 13:45:06 2021)
extra: e
b/BB:   modification time (Tue May 18 13:27:28 2021, Tue May 18 13:50:01 2021)
b/B:    modification time (Tue May 18 13:27:03 2021, Tue May 18 13:46:04 2021)
        sha256 (0x4f7986b5a925296c575043e73e76b59b6eb84da37c50f2e86baaafc75e2fcdca, 0x46f3f4e748cfef2a4cd679d6c9723cb44eb0526b760854fcef33bb97ca27fae2)
c/C:    permissions (0600, 0644)
missing: ./d

Line by line, mtree tells you that:

  • the path root directories themselves (.) have different timestamps
  • there is an extra entry e on hostB that does not appear on hostA
  • the modification time of entry b/BB differs between the two hosts (but the content does not)
  • the modification time AND the content (SHA256 hash) of entry b/B differ between the two hosts
  • the permissions of entry c/C differ between the two hosts
  • hostB is missing the entry ./d

AFAIK diff alone can't do that, but if you are using shell which supports process substitution (like bash/zsh) you can incorporate state command into diff like this

#working example:

echo "some file" > foo
cp foo bar
diff <(stat foo) <(stat bar)

chmod o+x bar
diff <(stat foo) <(stat bar)

NOTE that process substitution is not POSIX compliant so if you need something with more portability you will need to script it yourself. Above diff command can be roughly translated to POSIX like this:

mkfifo /var/tmp/fifo1
mkfifo /var/tmp/fifo2
stat foo >/var/tmp/fifo1 &
     stat bar >/var/tmp/fifo2 &
     diff /var/tmp/fifo1 /var/tmp/fifo2
rm /var/tmp/fifo1 /var/tmp/fifo2

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .