28

I am importing a file to my server using this command:

scp zumodo@shold:/test/test/test/server.py /test/test/test/test.py~/;

I want to restart my server if the newly imported file test.py~ differs from the test.py that already exists. How would I do this using a shellscript?

Spencer
  • 21,348
  • 34
  • 85
  • 121
  • I hope you mean "restart my daemon" not "restart my server" – sorpigal Nov 15 '11 at 16:46
  • You probably don't want the final '/;' on that command, because it's not a directory and you don't have another command on the same line. – Steve C Nov 15 '11 at 16:51
  • @peter do you mean if a load of files is different to one file and check each one? in your comment on my answer below. – gadgetmo Nov 15 '11 at 17:06

4 Answers4

65
if ! cmp -s test.py test.py~
then
  # restart service
fi

Breaking that down:

  • cmp -s test.py test.py~ returns true (0) if test.py and test.py~ are identical, else false (1). You can see this in man cmp. The -s options makes cmp silent, so it doesn't give any output (except errors), but only an exit code.
  • ! inverts that result, so the if statement translates to "if test.py and test.py~ are different".

ps: If you are not sure the 2nd file exists, you may want check that too. (cmp still works in this case, but gives an error message, suppressing error message may be enough too (cmp ... 2>/dev/null)

redseven
  • 849
  • 6
  • 11
Andrew Schulman
  • 3,395
  • 1
  • 21
  • 23
  • +1, but -q is non-standard. Redirect to /dev/null will always work. – William Pursell Nov 15 '11 at 17:01
  • Sorry, could someone explain the first line for a bash noob? What is the precedance for the argument of the if operator? Why are there those two redirects and what do they mean? –  Apr 24 '15 at 15:32
  • @AndrewSchulman: Thanks, I used in a script. If I understand this, the Boolean output and the stdout are both sent to the if, so to just have the boolean answer, you have to send the stdout to the bit bucket. –  Apr 29 '15 at 21:46
  • `if` always uses just the exit status (0/1) of the command. stdout will go to the terminal, so the redirects just make that be quiet. – Andrew Schulman Apr 30 '15 at 12:00
  • 4
    You could also use `cmp -s` to suppress terminal output of the comparison. – user448810 Jun 30 '15 at 19:02
  • Why does bash's if treat a return (0) as true, and (1) as false? Isn't that counter-intuitive to conventional boolean logic? – Poly Bug Oct 19 '15 at 04:26
  • 2
    @PolyBug: Yes, it is, but it's the convention in Unix/Linux. The reason is that there's only one type of success, but there can be many types of failure, which can return different status codes. See for example the Exit Status sections of `man ls` or `man grep`. – Andrew Schulman Oct 20 '15 at 07:35
  • 3
    This will be correct even if the file/files do not exists. – Király István Dec 08 '15 at 03:30
8

You could diff() the two files. A return code of zero (0) means there are no differences. A return code of one (1) says the files differ.

JRFerguson
  • 7,426
  • 2
  • 32
  • 36
0

diff <path_to_file_1> <path_to_file_2> && echo "files are same"

Daniel Lazar
  • 101
  • 8
0

I'd do something like

zumodo@shold$ cat /test/test/test/server.py | ssh zumodo@otherhost 'cat - > /test/test/test/test.py.new ; cmp /test/test/test/test.py /test/test/test/test.py.new || (mv /test/test/test/test.py.new /test/test/test/test.py ; echo issue restart command here)'
sorpigal
  • 25,504
  • 8
  • 57
  • 75