添加链接
link之家
链接快照平台
  • 输入网页链接,自动生成快照
  • 标签化管理网页链接
Collectives™ on Stack Overflow

Find centralized, trusted content and collaborate around the technologies you use most.

Learn more about Collectives

Teams

Q&A for work

Connect and share knowledge within a single location that is structured and easy to search.

Learn more about Teams

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

diff has exit status which can be tested directly, without using another executable namely '['. – niry Sep 10, 2016 at 21:06 The answer deserves some explanation about comparing exit code vs. comparing the output of the command. – sschuberth Jan 21, 2017 at 11:54 This is vastly inefficient as opposed to using cmp instead. diff is a much slower and more expensive tool, and you only need to use it when you want to know exactly what the difference is, not whether there is one or not. – Charles Duffy Oct 20, 2017 at 21:36 @CharlesDuffy - cmp lacks functionality that might be needed in the comparison. One example being ignoring lines in the comparison. – Adrian Lynch Feb 18, 2020 at 15:51 This is the most direct way of doing the test. (Note: you should add a close quote to the echo command.) – Gordon Davisson Sep 1, 2010 at 3:31 diff may send messages to stderr too, like permission denied errors, depending on your version – Xen2050 Apr 4, 2016 at 12:18 This answer works perfectly, but I'm confused by the negation (!), given the diff manpage: "Exit status is 0 if inputs are the same, 1 if different, 2 if trouble." Doesn't that mean it should be working the other way around? if ! diff.. then echo "same"? – Joshua Goldberg May 5, 2017 at 18:30 @JoshuaGoldberg bash's if operates differently than C. It does the conditional if the return is 0. Check out the man page for the test command - it returns 0 if true and 1 if false. – Paul Tomblin May 6, 2017 at 19:14

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";
                If you use this approach, be careful to do the test immediately after the 'diff' command. This is important as $? contain the return code of the LAST command.
– Édouard Lopez
                Jul 18, 2012 at 10:05

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

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.

Thanks for contributing an answer to Stack Overflow!

  • Please be sure to answer the question. Provide details and share your research!

But avoid

  • Asking for help, clarification, or responding to other answers.
  • Making statements based on opinion; back them up with references or personal experience.

To learn more, see our tips on writing great answers.