0

I want to check if a file exist, isn't empty and equal to another file. If so, do nothing.

If they aren't equal then overwrite both files with cat "some text".

If they don't exist or are empty then also create file with cat some text

I tried a few solutions, but whenever I get one condition right it makes another fail, or fail when no files exist.

What would be the cleanest way to solve this issue? All of this using bash?

  • While bash has some file test operators, it's not much of a text editor; did you mean that you were looking for a command-line-based solution? – Jeff Schaller Nov 3 '17 at 13:24
5
if [ -f file1 ] && [ -s file1 ] && [ -f file2 ] && [ -s file2 ] &&
    cmp file1 file2 &>/dev/null; then
    : do nothing in this case only
else
    echo "some text" >file1
    echo "some text" >file2 # or cp file1 file2
fi

and a shorter version, based on the comments

if [ -s file1 ] && cmp file1 file2 &>/dev/null; then
    : do nothing in this case only
else
    echo "some text" >file1
    echo "some text" >file2 # or cp file1 file2
fi
  • lol you did what it took me ~40 lines to solve in just 7 lines. Thanks – Freedo Nov 3 '17 at 2:36
  • 1
    I think we can drop the && [ -s file2 ], because if file2 would be empty at this point, the cmp would fail. – user1934428 Nov 3 '17 at 6:55
  • 1
    Also, if [ -s something ] is true, then [ -f something ] would be true as well, unless it's a non-regular file (but then cmp would fail). – Kusalananda Nov 3 '17 at 9:43
  • @Kusalananda, cmp works on non-regular files as well. It's common to use it on fifos for instance (though here, you would probably want to abort with an error if either file was a fifo). There's also a potential problem with those approaches for files for which you have write but not read permission (in which case you could end up overwriting them even though they are identical). Unlikely in practice. – Stéphane Chazelas Nov 3 '17 at 15:40
1

I would do a

if ! ( [[ -s file1 ]] && cmp file1 file2 2>/dev/null 1>&2 )
then
  echo "some text" >file1
  cp file1 file2
fi

Explanation:

-s file1 evaluates to true if file1 exists and is not empty.

The cmp command sets status code 0 if both files exist and are identical.

This is the case where we do not want to touch them, hence I prefix this by and exclamation mark, to negate the condition.

  • this would probably fail if file2 doesn't exist? – Freedo Nov 3 '17 at 7:49
  • No, it works in this case too: If file2 does not exist, cmp writes an error message to stderr (which is not displayed due to redirection) and returns an exit code different from zero. This makes the && expression false, the if becomes true, and the files are created. – user1934428 Nov 3 '17 at 11:04
1

Using the cmp -s option:

#!/bin/bash

if ! ( [[ -s file1 ]] && cmp -s file1 file2 )
then
    echo "some text" > file1
    cp file1 file2
fi

The -s option silently discards all output to stdout and stderr and just returns the exit status.

  • 1
    How, and why, does this differ from two previous answers? – Stephen Rauch Nov 3 '17 at 13:33
  • @StephenRauch. Uses the cmp -s option instead of redirection to /dev/null – fpmurphy Nov 3 '17 at 14:43
  • @StephenRauch. I never claimed my answer was better. – fpmurphy Nov 3 '17 at 15:12
  • @StephenRauch. According to your definition, a good 50% of answers should not exist as they are similar to other existing answers. – fpmurphy Nov 3 '17 at 15:17
  • OK, sorry I brought it up. – Stephen Rauch Nov 3 '17 at 16:14

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.