Title: How to diff directories over ssh
Tags: linux;shell
Question: I am trying to recursively compare a directory in the local host to a directory in a remote linux machine. However, when i execute the next command:
diff -r 'ssh woodarddavid@example.com:/home/admin' /home/admin
it doesn't work saying:
diff: ssh woodarddavid@example.com:/home/admin: No such file or directory
what is the right way to compare recursively the directories contents?
Thanks in advance
Comment: this link tells how to compare files. it doesn't work in comparing dirs

Comment: Related: http://serverfault.com/questions/59140/how-do-diff-over-ssh

Here is the accepted answer: If you needn't diff the detail in file, just get the difference of dir/file name, then try this:
(Note: need set "SSH login without password" , for detail , review this URL:  http://www.linuxproblem.org/art_9.html)
diff <(ssh woodarddavid@example.com ls -R /home/admin) <(ls -R /home/admin)
Comment for this answer: Be aware, using `ls` you may run into some of the same limitations and problems with using `ls` to drive a `for` loop ( [**why for i in $(ls *.mp3) - is wrong**](http://mywiki.wooledge.org/BashPitfalls#for_i_in_.24.28ls_.2A.mp3.29) although process substitution will catch most of them
Comment for this answer: The `ls` formatting could differ on the machines. Therefore you should ensure that each file appears in a new line: `ls -1R`.
Also note that this doesn't work nicely if the base-path (here `/home/admin`) differs.
Comment for this answer: Also - this only works because the path of the source and destination is the same (`/home/admin`). If the paths are different you will need something like `cd $path && ls -R` instead of `diff $path`
Comment for this answer: You need set non-password for SSH session first
Comment for this answer: I updated my answer, please review this URL http://www.linuxproblem.org/art_9.html
Comment for this answer: Diff command listed here gives error "Missing name for redirect" on Centos Linux.   But you can just redirect the "ls -R" output to local files and diff the local files.   I'm also using the command "find . -type f" which lists the directory and file name in one path.  Doesn't have the elegance of the above solution, but it works for me.
Comment for this answer: when ssh asks for password, it is automatically answered because of the second operator < which tunnels its output as password as follows:
diff <(ssh woodarddavid@example.com find /home/admin -printf '"%8s %p\n"')  <(find /home/admin -printf '%8s %p\n')
This system is for authorized use only.
woodarddavid@example.com's password:
Permission denied, please try again.
woodarddavid@example.com's password:
Permission denied, please try again.
woodarddavid@example.com's password:
Permission denied (publickey,password).

Here is another answer: You can mount the remote directory via sshfs, then you can use diff -r to compare the two directories as you want to do it.
Alternatively you could run similar find commands on both machines to print the file trees (e. g. file names, sizes, and dates) and then compare the outputs of both using diff.  This would not compare file contents, of course:
diff <(ssh host find /home/admin -printf '"%8s %P\n"') \
<(find /home/admin -printf '%8s %P\n')
Notice the double quoting of the printf-format string in the ssh call.  One layer is removed by the ssh relay.
Comment for this answer: You might find it useful to `sort` the outputs of `find` commands before comparing them via `diff`; in that case I'd use the path as first element in the output:  `<(find /home/admin -printf "%p %s\n" | sort)`
Comment for this answer: Thanks @reox, I changed my answer accordingly.  Actually, I typically use this within a `(cd dir; find . -printf …)` in which case it does not make any difference whether `%p` or `%P` is used.  Here it does.
Comment for this answer: @WolfgangBlessen In any case keep in mind that `sshfs` is a file system via a network and (basically) reduced to one user because whatever is done on the remote host is done with the permissions of the user who setup the underlying ssh connection.  These limitations sometimes lead to problems because some special file system features might not be properly implemented in `sshfs` and a tool like an IDE might rely on such.  In my experience, however, these situations are extremely rare.  Most problems arise from network outages (but that you could have with any network solution).
Comment for this answer: better use %P than %p, so you can diff directories that are in a different folder on each server
Comment for this answer: +1 for the Hint to sshfs, which allows to use the mounted Directory in an IDE like phpStorm or other Deployment Tools
Comment for this answer: @Alfe To compare Web Installations of a Project, I now use two special ssh Users for that Application. Comparing then works fine with meld.

Here is another answer: Try using "rsync" with the "-n" option, which just does a "dry run" and tells you what it would do.
Comment for this answer: Example for @FlorianBrucker suggestion:
`rsync --itemize-changes --dry-run -r -c downloads/ woodarddavid@example.com:/home/user/downloads/`
Comment for this answer: of course you also need `-r` or `-a` for your recursion, and don't forget to add the backslashes after directory names (but then no star), otherwise somehow `--delete` doesn't return any deletions. so your command would be `rsync -e 'ssh -p 22' -azvn --delete woodarddavid@example.com:/home/admin/ /home/admin/`.
Comment for this answer: `--delete` is needful. Without it, you won't see any files that are present on the 2nd machine but not on the 1st. Make sure you have the dry run `-n` option.
Comment for this answer: @MartinH. Great. Can you please move your last comment `rsync` example into your answer ?
Comment for this answer: `-c` will tell rsync to look at checksums, not just date & length
Comment for this answer: Another handy option: `--itemize-changes` (`-i`) will tell you for each file [what has changed](http://andreafrancia.blogspot.de/2010/03/as-you-may-know-rsyncs-delete-options.html).

Here is another answer: I find krusader very useful for such task in case you need a GUI.
See https://www.linux.com/news/synchronize-directories-komparator-and-kdiff3 for more details http://krusador.org.
example folder compare

Here is another answer: For all the examples below empty folders do not matter.
If the password is not required for ssh and you want to see the files
diff -y -W250 \
<(ssh user@host1 &quot;find /jbossas/modules -type f | xargs -I{} md5sum {} | sort -k2&quot;)
<(ssh user@host2 &quot;find /jbossas/modules -type f | xargs -I{} md5sum {} | sort -k2&quot;)
If the password is not required for ssh and you just want to know if the folders are the same
diff -y -W250 \
<(ssh user@host1 &quot;find /jbossas/modules -type f | xargs -I{} md5sum {} | sort | md5sum&quot;) \
<(ssh user@host2 &quot;find /jbossas/modules -type f | xargs -I{} md5sum {} | sort | md5sum&quot;)
If password is required for ssh
Install the sshpass package
Receive your password securely in the PASS variable (the password will be cleared in 60 seconds): echo -n &quot;Password: &quot;; IFS= read -rs PASS < /dev/tty; trap 'unset PASS; echo &quot;PASS has been cleared&quot;; trap - USR1' USR1; { sleep 60; kill -USR1 $$; } &amp;
diff -y -W250 \
<(sshpass -p &quot;$PASS&quot; ssh user@host1 &quot;find /jbossas/modules -type f | xargs -I{} md5sum {} | sort | md5sum&quot;) \
<(sshpass -p &quot;$PASS&quot; ssh user@host2 &quot;find /jbossas/modules -type f | xargs -I{} md5sum {} | sort | md5sum&quot;)
If sudo is needed on the remote host
diff -y -W250 \
<(ssh user@host1 &quot;echo \&quot;$PASS\&quot; | sudo -S find /jbossas/modules -type f | xargs -I{} md5sum {} | sort | md5sum&quot;) \
<(ssh user@host1 &quot;echo \&quot;$PASS\&quot; | sudo -S find /jbossas/modules -type f | xargs -I{} md5sum {} | sort | md5sum&quot;)
And you can merge the options.
I recommend icdiff instead of diff, but diff is enough.

Here is another answer: Building on the answer of @MarkSetchell and the discussion underneath:
If you want to use rsync for the diff, here is an example:
rsync --itemize-changes --dry-run -r -c downloads/ woodarddavid@example.com:/home/user/downloads/

Here is another answer: I use  | less at the end of the command for interactive password prompts and sdiff because it is easier to read than diff :
So between local and remote, type :
sdiff -s <(find $dir -printf &quot;%p\t%s\n&quot; | sort) <(ssh server1 find $dir -printf '&quot;%p\t%s\n&quot;' | sort) | less
and between two servers, type :
sdiff -s <(ssh server1 find $dir -printf '&quot;%p\t%s\n&quot;' | sort) <(ssh server2 find $dir -printf '&quot;%p\t%s\n&quot;' | sort) | less
where $dir is the full directory path you want to compare.

{'source': 'StackExchangeDataset', 'subset': 'stackoverflow.com', 'metadata': {'AnswerCount': 7, 'CommentCount': 2, 'ContentLicense': 'CC BY-SA 3.0', 'CreationDate': '2014:00:01/07/14', 'FavoriteCount': 25.0, 'PostTypeId': 1, 'Tags': '<linux><shell>', 'Title': 'How to diff directories over ssh', 'ViewCount': 55961, 'id': 20969124, 'user_AboutMe': '<h1>whoami</h1>\n<p>My name is Hesham, A husband, and a father. Software Engineering is my bread and butter. It is also a hobby. Usually, I love what I do at work. When things get boring at work, I find it an opportunity to create new features and functionalities.</p>\n<h2>my experience</h2>\n<ul>\n<li>Cloud Architecture; <code>Microservices</code> design and development - <code>Paas</code>, <code>SaaS</code>.</li>\n<li>Mobile; <code>Android</code>, <code>Javascript</code>, <code>NodeJs</code>, <code>ReactNative</code></li>\n</ul>\n<h2>howsharpami</h2>\n<p><strong>Always Active</strong>, <strong>Always Ready</strong>; Reading, Writing and developing. you can subscribe to my blog <code>https://heshamy.com</code>. or take a look at my [github][1].</p>\n<ul>\n<li>LinkedIn: <a href="https://www.linkedin.com/in/heshamy/" rel="nofollow noreferrer">https://www.linkedin.com/in/heshamy/</a></li>\n<li>GitHub: <a href="https://github.com/exhesham" rel="nofollow noreferrer">https://github.com/exhesham</a></li>\n</ul>\n', 'user_AccountId': 2877492.0, 'user_DisplayName': 'Hesham Yassin', 'user_Reputation': 4281.0, 'user_Views': 528.0, 'user_id': 2469134.0}}