Ever wanted to do a diff between a local file and a remote one? I have, so I wrote a simple shell script that'll do it for you. It requires scp
, diff
, and rm
to be available on your system, which should be the case on any modern *nix. The -b
option to diff tells it to ignore white-space difference. If you don't have password-less SSH authentication set up, you'll want to remove the >& /dev/null
trailers from the two scp
lines so you get your prompts.
To run, just drop this into /usr/bin
(or somewhere else on your path), make it executable, and call it just like diff
, except with scp
-compatible file paths.
#!/bin/sh # # this acts as a remote diff program, accepting two files and displaying # a diff for them. Zero, one, or both files can be remote. File paths # must be in a format `scp` understands: [[user@]host:]file if [ "$1" = "" -o "$2" = "" ]; then echo "Usage: `basename $0` file1 file2" exit 1 fi scp $1 rdiff.1 >& /dev/null scp $2 rdiff.2 >& /dev/null diff -b rdiff.1 rdiff.2 rm -f rdiff.1 rdiff.2
Update: Horst and Amit both posted a far better solution that leverages SSH directly. Back when I wrote this I didn't appreciate SSH's power for more than interactive shells. Here's his command (replaced the brace-wrapped strings as needed):
ssh {remote_host} cat {remote_file} | diff {local_file} -
Great script, thanks a lot!
this will happily overwrite the two files "rdiff.1″ and "rdiff.2″, should they exist in the current directory.
if you really want to diff a _local_ file and a remote one, use something like
ssh remotehost 'cat remotefile' | diff – localfile
…and you don't have to worry about how to create good temporary files
horst,
You are right, of course. A much better way to do it. I seem to be constantly forgetting how darn versatile ssh is: so much more than just a secure shell.
What I actually have to write, and soon, is a remote *recursive* diff. Write it, or find one (which is how I got here :)
For recursive diff, you could try using nfs, and pretend they are both local. Obviously using –recursive with diff :-)
NFS wont be so great with your transit costs if you have lots of large files though. Great for LAN environments! – -
Recursive remote diff?? Aren't we getting into svn/cvs at that point :)
I think it's worth to add option to pass diff option
if [ $3 = "" ]
then
opt="-b"
else
opt=$3
fi
The simplest way to do remote diff is as follows:
ssh {remote_host} cat {remote_file} | diff {local_file} -
@Amit
That is definitely a better solution. In my defense, when I posted this (3.5 years ago) I didn't "get" that `ssh` could be anything more than a secure remote interactive shell. I've since learned better. : )
That was a solution suggested to me by my Perl/Unix instructor, the revered Dr. Tim Maher. The beauty of it is that it cleans up after itself.
A bit tweaked version of your script:
http://larryn.blogspot.com/2009/01/remote-diff.html
Recursive remote diff:
cd {local-dir}
for i in `find {subdir} -type f ` ; do echo "=== $i ===" ; ssh {remote-user}@{remote-host} "cat {remote-dir}/$i" | diff – {local-dir}/$i ; done
Example:
cd ~/root-of-my-local-project-dir
for i in `find app/controllers/ -type f ` ; do echo "=== $i ===" ; ssh bob@foo.remote-server.com "cat root-of-remote-project-dir/$i" | diff – ~/root-of-my-local-project-dir/$i ; done
Note: {subdir} can be "." if you want everything from {local-dir}
Nice script !
but i think it require that the two folders have the same files.
if a file exists only in local dire, what will say this script
Thanks
Hi,
Thanks for sharing this useful information.
I'm trying to do a diff between remote servers for directories.
I've tried multipe variables there (S,s,p,q,r) etc, but I can only see the below response
bash: /home/bkesavan: is a directory
Is it achievable through diff?
Bhargav,
The first half of your command is trying to execute a directory via SSH, which doesn't make any sense. That's what the error message is showing. My script used SCP to move files locally and do a local diff. An improvement is to use a stream (as Amit suggested above), though that only allows for one remote file (not two). A directory can't be streamed like that, however, you'll need to walk the directory and do file-by-file comparisons unless you pull the whole directory to the local machine and do a local recursive diff.
So the short answer is "no, not really".
Thanks for your reply Barney.
I've tried it using rsync and it's working fine for me.
I used rsync -nr :/home/bkesavan/test/
Thank you.
I think the brackets didn't show up in my previous comment.
It's like this
rsync -nr remote_server:/home/bkesavan/test/ Local_server_dir_path