I need to know if a file aready has line with contents X in it, if not append line. here's the code I've tried.

if ! $(grep 'eval $(perl -I$HOME/foo/lib/perl5 -Mlocal::lib=$HOME/foo)' ~/.bashrc)
    echo 'eval $(perl -I$HOME/foo/lib/perl5 -Mlocal::lib=$HOME/foo)' >> ~/.bashrc

4 Answers 4


LINE='eval $(perl -I$HOME/foo/lib/perl5 -Mlocal::lib=$HOME/foo)'

if ! grep -qF "$LINE" file.txt ; then echo "$LINE" >> file.txt ; fi

The $(...) will return the result of the command, not the errorlevel value. Use without command substitution to get the proper return code.

  • The '!' command isn't always available in 'sh', IIRC (yeah, I know you used bash). It might be slightly more idiomatic sh to say: grep -qF "$LINE" file.txt || echo "$LINE" >> file.txt
    – Hari
    Jan 12, 2011 at 16:23
  • @Hari: ! wasn't in Bourne, but it is in POSIX. Jan 12, 2011 at 21:30

To search for a literal string:

line='eval $(perl -I$HOME/foo/lib/perl5 -Mlocal::lib=$HOME/foo)'
if ! grep -q -x -F -e "$line" <"$file"; then
  printf '%s\n' "$line" >>"$file"

-q suppresses grep output (you're only interested in the return status). -x requires the whole line to match. -F searches for a literal string rather than a regexp. -e is a precaution in case $line starts with a -.


You may have better luck with awk's index function: it's an equivalent of strstr, so should be well-suited for comparision (as opposed to grep which is for pattern matching).


You can do this with sed. The issue is that you need to include the string in the code twice. Once to test it, again to insert it.

sed -i '/eval \$(perl -I\$HOME\/foo\/lib\/perl5 -Mlocal::lib=\$HOME\/foo)/!{ ${ s/$/\neval \$(perl -I\$HOME\/foo\/lib\/perl5 -Mlocal::lib=\$HOME\/foo)/; }; }' /path/to/file

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.