Remote Diff

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} -

17 responses to “Remote Diff”

  1. muriloq

    Great script, thanks a lot!

  2. horst

    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

  3. Barney

    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.

  4. Jürgen

    What I actually have to write, and soon, is a remote *recursive* diff. Write it, or find one (which is how I got here :)

  5. Kul

    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! – -

  6. John Hunt

    Recursive remote diff?? Aren't we getting into svn/cvs at that point :)

  7. Wawrzek

    I think it's worth to add option to pass diff option

    if [ $3 = "" ]
    then
    opt="-b"
    else
    opt=$3
    fi

  8. Amit

    The simplest way to do remote diff is as follows:
    ssh {remote_host} cat {remote_file} | diff {local_file} -

  9. Amit

    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.

  10. Wawrzek

    A bit tweaked version of your script:

    http://larryn.blogspot.com/2009/01/remote-diff.html

  11. The Best Place on Earth

    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}

  12. Aymen

    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

  13. Bhargav Kesavan

    Hi,

    Thanks for sharing this useful information.

    I'm trying to do a diff between remote servers for directories.

    ssh  "/home/bkesavan" | diff -S /home/bkesavan/
    

    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?

  14. Bhargav Kesavan

    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.

  15. Bhargav Kesavan

    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