Appending a line to a file if absent

echogrepmaketext processing

I'd like to add a series of commands to a Makefile that append config lines when they are not already present. I've done this in the past in a manner like so:

grep -vq "keyword" /a/b/c.conf && echo "abc keyword" >> /a/b/c.conf

But, I'm clearly overlooking something. The command as-is causes the config line to be duplicated when re-run.

A manual test shows the pattern works as expected:

grep -vq "keyword" /a/b/c.conf && echo "the line is absent"

… prints the line is absent only when the line is actually absent. And, the echo command is correctly not executed when the line is present.

What am I missing?


Note: The examples above are condensed for readability. In reality, there will be many similar commands. Here's the particular command I've tried:

grep -vq "md_module" /etc/httpd/conf.modules.d/00-ssl.conf && echo "LoadModule md_module modules/mod_md.so" >> /etc/httpd/conf.modules.d/00-ssl.conf

Best Answer

The problem is that grep -v will match lines that do not match the expression, not files that do not match it...

So if your file has any lines that do not match it, grep -v will match those lines and so grep will return successful.

A better approach is to use a positive match for the keyword and then use || (instead of &&) to append the line if needed:

grep -q "keyword" /a/b/c.conf || echo "abc keyword" >> /a/b/c.conf

You probably got your test with echo "the line is absent" to say it was absent when it was indeed absent... And maybe to do nothing if that was the only line. If you test this further, I think you'll see that as long as it does have any lines that do not match keyword, you'll get a match.

I hope this clarifies it!

Related Question