69

I wanted to be clever and compare a remote file to a local file without first manually downloading it. I can get the contents of the remote file by

ssh user@remote-host "cat path/file.name"

However, piping that to diff

ssh user@remote-host "cat path/file.name" | diff path/file.name

gives me this:

diff: missing operand after `path/file.nae'
diff: Try `diff --help' for more information.

I have ssh keys set up, so it's not prompting me for a password. What's a workaround for this?

  • 5
    By the way, you're still downloading the file when you do this (since its content gets sent over the SSH connection), you're just not saving it anywhere. So it's not like you save any bandwidth or anything. – David Z Aug 21 '10 at 0:13
  • 2
    Yeah, I just don't want to muck up my file system with one-shot files hanging around. – user394 Aug 23 '10 at 13:29
  • 1
    for when the command does not support stdin (e.g. via -), you can use /dev/stdin. e.g. diff file1 /dev/stdin – ctrl-alt-delor Mar 15 '17 at 19:46
86

Try to use - to represent the standard input.

ssh user@remote-host "cat path/file.name" | diff path/file.name -

  • when comparing giant files (such as linux disk images) this is outputting them all to the console! even with diff -s (for "same") it does this. – user391339 Oct 20 '14 at 1:53
58

Here's one workaround: diff seems to accept <(expr) as arguemnts:

diff <(ssh \"cat path/file.name/") <(cat path/file.name)
  • 16
    That's not diff, that's the shell (bash, ksh and zsh support this syntax, but it's not POSIX), with some help from the kernel (it must provide /dev/fd: diff sees something like /dev/fd/3 on its command line). – Gilles Aug 20 '10 at 19:25
  • 2
    It doesn't "must provide" - shells can create temporary named pipes for this feature too. – ephemient Sep 24 '10 at 14:11
  • 3
    this is the coolest answer! – neves Dec 20 '11 at 21:47
  • 6
    I personally prefer this answer. I needed to diff two different XML files; but they needed to be properly formed first. That led to this: diff -y <(xmllint --format "${1}") <(xmllint --format "${2}") which I now use all the time. – Paul Nelson Baker Oct 8 '14 at 19:49
  • This is also very useful on OS X where one might want to compare two binary .plist files: diff <(plutil -convert xml1 -o -- "${1}") <(plutil -convert xml1 -o - -- "${2}") – morgant Feb 16 '15 at 18:57
4

Piping into diff is equivalent to running

diff path/file.name

and then, once it's running, typing the entire contents of the file.

As you can see, that's not what you expected.

  • No workaround? :( – user394 Aug 20 '10 at 18:56
  • 1
    Look at Hemant's answer. I didn't know of one. – Macha Aug 20 '10 at 18:59
1
diff /tmp/localtempfile <(ssh -A -o StrictHostKeyChecking=no root@server "cat /tmp/remotetempfile")
  • What is with the lowering of security StrictHostKeyChecking=no? Otherwise a good answer. – ctrl-alt-delor Mar 15 '17 at 19:48

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.