Bash: using the result of a diff in a if statement

BashDiff

Bash Problem Overview


I am writing a simple Bash script to detect when a folder has been modified.

It is something very close to:

ls -lR $dir > a
ls -lR $dir > b

DIFF=$(diff a b) 
if [ $DIFF -ne 0 ] 
then
    echo "The directory was modified"

Unfortunately, the if statement prints an error: [: -ne: unary operator expected

I am not sure what is wrong with my script, would anyone please be able to help me?

Thank you very much!

Jary

Bash Solutions


Solution 1 - Bash

ls -lR $dir > a
ls -lR $dir > b

DIFF=$(diff a b) 
if [ "$DIFF" != "" ] 
then
    echo "The directory was modified"
fi

Solution 2 - Bash

if ! diff -q a b &>/dev/null; then
  >&2 echo "different"
fi

Solution 3 - Bash

You are looking for the return value of diff and not the output of diff that you are using in your example code.

Try this:

diff a b
if [ $? -ne 0 ]; then
    echo "The directory was modified";
fi

Solution 4 - Bash

If you don't need to know what the changes are, cmp is enough. Plus you can play with the syntactical trick provided by && and || :

cmp a b || echo 'The directory was modified'

The instruction may be interpreted as: "either a and b are equal, or i echo the message".

(The semantic of && and || must be handled with care, but here it's intuitive).

Just for the sake of readability, i actually prefer to put it on two lines:

cmp a b \
  || echo 'The directory was modified'

Solution 5 - Bash

DIFF=$(diff -u <(find dir1/ -type f -printf '%P\n' | sort) <(find dir2/ -type f -printf '%P\n' | sort))
if [ "$DIFF" ]; then
  echo "Directories differ"
  # Do other stuff here
fi

This uses one of my favorite bashisms, the <() process substitution.

The $DIFF variable holds a printable difference. If you want to show it to the end user, be sure to double-quote it, e.g. echo "$DIFF".

If you want to only tell the user there was any difference, if can be shortened to something like [ "$(diff ...)" ] && echo "Difference found"

Note: I'm assuming the original question meant to have dir1 and dir2 to make a little more sense. If it was dir at time 0 and then dir at time 1, this approach obviously wouldn't work.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionJaryView Question on Stackoverflow
Solution 1 - BashLou FrancoView Answer on Stackoverflow
Solution 2 - BashPaul TomblinView Answer on Stackoverflow
Solution 3 - BashtangensView Answer on Stackoverflow
Solution 4 - BashChristophe PriieurView Answer on Stackoverflow
Solution 5 - BashAaron D. MarascoView Answer on Stackoverflow