411

I want to check if a file contains a specific string or not in bash. I used this script, but it doesn't work:

 if [[ 'grep 'SomeString' $File' ]];then
   # Some Actions
 fi

What's wrong in my code?

codeforester
  • 39,467
  • 16
  • 112
  • 140
Hakim
  • 11,110
  • 14
  • 34
  • 37
  • 3
    Similar to http://stackoverflow.com/questions/4749330/how-to-test-if-string-exists-in-file-with-bash-shell – Pawel Nov 18 '14 at 10:26
  • Here's how to grep the output of a `command`: https://stackoverflow.com/questions/12375722/how-do-i-test-in-one-line-if-command-output-contains-a-certain-string – rogerdpack Nov 23 '19 at 16:17

11 Answers11

715
if grep -q SomeString "$File"; then
  Some Actions # SomeString was found
fi

You don't need [[ ]] here. Just run the command directly. Add -q option when you don't need the string displayed when it was found.

The grep command returns 0 or 1 in the exit code depending on the result of search. 0 if something was found; 1 otherwise.

$ echo hello | grep hi ; echo $?
1
$ echo hello | grep he ; echo $?
hello
0
$ echo hello | grep -q he ; echo $?
0

You can specify commands as an condition of if. If the command returns 0 in its exitcode that means that the condition is true; otherwise false.

$ if /bin/true; then echo that is true; fi
that is true
$ if /bin/false; then echo that is true; fi
$

As you can see you run here the programs directly. No additional [] or [[]].

rogerdpack
  • 62,887
  • 36
  • 269
  • 388
Igor Chubin
  • 61,765
  • 13
  • 122
  • 144
  • More information about `grep` and available options in asnwer http://stackoverflow.com/a/4749368/1702557 – Pawel Nov 18 '14 at 10:27
  • 2
    might want to consider `-Fxq` parameters as in http://stackoverflow.com/a/4749368/544721 – Grzegorz Wierzowiecki Apr 23 '16 at 08:52
  • 4
    consider using `-m 1` in order to improve scanning performance. Returns on the first occurrence. – AlikElzin-kilaka Jan 17 '17 at 12:08
  • 1
    if `SomeString` contains regex special characters (like `.`) you might get unexpected results. It's safer to always use `fgrep` (or `grep -F`) (unless you really need a regex, in which case `egrep` (or `grep -E`) is probably the best choice) – Walter Tross Apr 27 '18 at 13:25
  • 1
    The example `if` example is incorrect, as it only checks if the exit code was non-0. If any error happens, like the file can't be read, the exit code is also non-0. So you have to do something like `ec=$?`, and check if it's `0` (found), then if it's `1` (not found), and then if it's something else (fail). – ddekany Jun 08 '19 at 06:16
  • 2
    `if ! grep -q SomeString ...` If you want to negate, use a `!` and a space. – Cameron Tacklind Sep 28 '19 at 09:05
  • What if I'm using ```set -e```? – Paul Knopf Dec 09 '19 at 00:14
  • @PaulKnopf: `set -e` does not interfere with `if` – Igor Chubin Dec 12 '19 at 21:08
  • What is the result of `echo hello | grep hi` or `echo hello | grep he`, question for bash starters like me;) This does not work: `if grep -q SomeString "$File"; then`, but this `if echo $file | grep -q SomeString ; then..` on a ..... guess what ... mac – Timo Feb 07 '23 at 20:02
  • If grep returns 0 on a successful match, why is the condition getting executed? Shouldn't the if condition be false? – Loner Apr 16 '23 at 18:30
  • @Loner: 0 exit code means true, or I didn't get your question? – Igor Chubin Apr 16 '23 at 19:38
102

In case if you want to check whether file does not contain a specific string, you can do it as follows.

if ! grep -q SomeString "$File"; then
  Some Actions # SomeString was not found
fi
Lahiru Chandima
  • 22,324
  • 22
  • 103
  • 179
  • 1
    Suppose you have several stings in an "input file" that you want to test. Can you combine your solution with `cat` (and `xargs`)? Or do you need a for loop? – qräbnö Jan 02 '21 at 17:22
  • Is this possible to compare lines from a variable to lines from a text file? Is there a way to set multiple lines to compare instead of `SomeString` ? – Bando Sep 10 '21 at 14:46
  • `grep -v` also negates the condition – Tom Harrison Jun 08 '22 at 20:47
49

In addition to other answers, which told you how to do what you wanted, I try to explain what was wrong (which is what you wanted.

In Bash, if is to be followed with a command. If the exit code of this command is equal to 0, then the then part is executed, else the else part if any is executed.

You can do that with any command as explained in other answers: if /bin/true; then ...; fi

[[ is an internal bash command dedicated to some tests, like file existence, variable comparisons. Similarly [ is an external command (it is located typically in /usr/bin/[) that performs roughly the same tests but needs ] as a final argument, which is why ] must be padded with a space on the left, which is not the case with ]].

Here you needn't [[ nor [.

Another thing is the way you quote things. In bash, there is only one case where pairs of quotes do nest, it is "$(command "argument")". But in 'grep 'SomeString' $File' you have only one word, because 'grep ' is a quoted unit, which is concatenated with SomeString and then again concatenated with ' $File'. The variable $File is not even replaced with its value because of the use of single quotes. The proper way to do that is grep 'SomeString' "$File".

Benoit
  • 76,634
  • 23
  • 210
  • 236
22

Shortest (correct) version:

grep -q "something" file; [ $? -eq 0 ] && echo "yes" || echo "no"

can be also written as

grep -q "something" file; test $? -eq 0 && echo "yes" || echo "no"

but you dont need to explicitly test it in this case, so the same with:

grep -q "something" file && echo "yes" || echo "no"
Telemachus
  • 19,459
  • 7
  • 57
  • 79
lzap
  • 16,417
  • 12
  • 71
  • 108
12
##To check for a particular  string in a file

cd PATH_TO_YOUR_DIRECTORY #Changing directory to your working directory
File=YOUR_FILENAME  
if grep -q STRING_YOU_ARE_CHECKING_FOR "$File"; ##note the space after the string you are searching for
then
echo "Hooray!!It's available"
else
echo "Oops!!Not available"
fi
Nevin Raj Victor
  • 2,924
  • 3
  • 23
  • 37
  • 2
    Changing directory is usually not a good idea (and is completely unnecessary here, just qualify the filename with the target directory). And then what you have is exactly the same thing as the accepted answer, only with less details. – Mat Feb 06 '15 at 07:05
11
grep -q [PATTERN] [FILE] && echo $?

The exit status is 0 (true) if the pattern was found; otherwise blankstring.

Eric Leschinski
  • 146,994
  • 96
  • 417
  • 335
SupermanKelly
  • 147
  • 1
  • 6
10
if grep -q [string] [filename]
then
    [whatever action]
fi

Example

if grep -q 'my cat is in a tree' /tmp/cat.txt
then
    mkdir cat
fi
Tlacenka
  • 520
  • 9
  • 15
bennie1
  • 167
  • 2
  • 3
8

In case you want to checkif the string matches the whole line and if it is a fixed string, You can do it this way

grep -Fxq [String] [filePath]

example

 searchString="Hello World"
 file="./test.log"
 if grep -Fxq "$searchString" $file
    then
            echo "String found in $file"
    else
            echo "String not found in $file"
 fi

From the man file:

-F, --fixed-strings

          Interpret  PATTERN  as  a  list of fixed strings, separated by newlines, any of 

which is to be matched.
          (-F is specified by POSIX.)
-x, --line-regexp
          Select only those matches that exactly match the whole line.  (-x is specified by 

POSIX.)
-q, --quiet, --silent
          Quiet; do not write anything to standard output.  Exit immediately with zero 

status  if  any  match  is
          found,  even  if  an error was detected.  Also see the -s or --no-messages 

option.  (-q is specified by
          POSIX.)
Shubham Khatri
  • 270,417
  • 55
  • 406
  • 400
  • It does not work. For instance , if i am looking for the line 'hello' and there is one line that says 'hello world' , the answer should be 'hello not found in file' as hello DOES NOT EQUAL THE ENTIRE LINE . – Berni Oct 28 '22 at 08:32
2

Try this:

if [[ $(grep "SomeString" $File) ]] ; then
   echo "Found"
else
   echo "Not Found"
fi
vgokul129
  • 777
  • 12
  • 31
  • 4
    I'm hesitantly abstaining from downvoting this, but Stack Overflow should not perpetuate this sort of pretzel logic. `grep` returns an exit status for a very good reason; capturing output into a string is potentially going to store a large amount of text in a buffer just so you can say it's non-empty. – tripleee Sep 06 '18 at 03:03
  • 1
    @tripleee this kind of answer is literally what downvotes are designed for. – jbg Apr 16 '22 at 13:48
-1

I done this, seems to work fine

if grep $SearchTerm $FileToSearch; then
   echo "$SearchTerm found OK"
else
   echo "$SearchTerm not found"
fi
  • 1
    [The quoting is broken](/questions/10067266/when-to-wrap-quotes-around-a-shell-variable), and you probably want to avoid seeing the output from `grep`. – tripleee Sep 06 '18 at 03:00
-3
grep -q "something" file
[[ !? -eq 0 ]] && echo "yes" || echo "no"
chemila
  • 4,231
  • 4
  • 22
  • 18
  • 2
    You have a typo - !? is supposed to be $? – lzap Jul 23 '12 at 12:18
  • 1
    ...not only is it intended to be `$?`, but there's no need for it at all -- you could just do `if grep -q ...` – Charles Duffy Jun 26 '13 at 12:41
  • 2
    Moreover, `foo && truthy_action || falsey_action` isn't a real ternary operator -- if `truthy_action` fails, then `falsey_action` gets run _in addition_. – Charles Duffy Jun 26 '13 at 12:42
  • More generally, the *purpose* of `if` is to run a command and check its exit code. You should very rarely need to examine `$?` explicitly. – tripleee Sep 06 '18 at 02:59