fab
fab

Reputation: 315

Check file existence and grep in the same if statement

I'm trying to append a string into a file if the file exists and if it is not already in it. Otherwise, create the file with the string in it.

if [ -f PATH_TO_FILE ]; then
  if ! grep -q PATTERN PATH_TO_FILE; then
    echo STRING >> PATH_TO_FILE
  fi
else
  echo STRING >> PATH_TO_FILE
fi

I want to optimize that with AND/OR conditions in the if statements but struggle with the syntax.

I tried to do the following but it does not work if the file does not exist.

grep -q PATTERN PATH_TO_FILE || echo STRING >> PATH_TO_FILE

Can anyone help me finding the sweetest syntax?

Upvotes: 2

Views: 2561

Answers (3)

Jahid
Jahid

Reputation: 22428

This can be done like this too:

[ ! -f PATH_TO_FILE ] || ! grep -q PATTERN PATH_TO_FILE && echo STRING >> PATH_TO_FILE

Explanation:

At first it checks for existing file. If it doesn't exist, the first condition is true and thus the miidle part (grep) is skipped and echo part is executed, i.e file is created with STRING in it. And if the file exist, the first condition is false, thus second condition is executed, and the echo part executes only if the grep part is true. Thus if the PATTERN matches, the echo part won't be executed i.e STRING won't be written in the file if PATTERN matches.

Example:

[ ! -f PATH_TO_FILE ] || ! grep -q STRING PATH_TO_FILE && echo STRING >> PATH_TO_FILE
[ ! -f PATH_TO_FILE ] || ! grep -q STRING PATH_TO_FILE && echo STRING >> PATH_TO_FILE

This will create a file named PATH_TO_FILE and write STRING in it. Even though the same code is executed two times, it won't write STRING twice. Because at second time, STRING is found in PATH_TO_FILE.

And if you execute it with a second STRING and PATTERN it will write to it:

[ ! -f PATH_TO_FILE ] || ! grep -q STRING2 PATH_TO_FILE && echo STRING2 >> PATH_TO_FILE

STRING2 will be appended to the file.

Upvotes: 0

anubhava
anubhava

Reputation: 785058

You can do:

if [[ ! -f PATH_TO_FILE ]] || ! grep -q PATTERN PATH_TO_FILE; then
   echo STRING >> PATH_TO_FILE
fi

Upvotes: 3

P.P
P.P

Reputation: 121377

This

grep -q PATTERN PATH_TO_FILE || echo STRING >> PATH_TO_FILE

does the equivalent functionality as the if ..else statements.

So, if you don't like to see the error message when the file doesn't exist, you could redirect stderr to /dev/null.

grep -q PATTERN PATH_TO_FILE 2>/dev/null || echo STRING >> PATH_TO_FILE

Upvotes: 4

Related Questions