3

I have been trying to write a script that will checks if the specific content is not found in specific files/folders then it should print "failed". else it should print "success". However, the following script causing multiple errors.

if [[ ( ! grep '/example.com' /opt/nfs &>/dev/null ) || ( ! grep -R '/example.com' /data &>/dev/null) ]]
then
echo "Failed"
else
echo "Passed"
fi

Can anyone tell me why it's causing errors and is there anyway to eliminate the errors and get the expected output?

UPDATE: I'm getting following errors:

s.sh: line 1: conditional binary operator expected
s.sh: line 1: expected `)'
s.sh: line 1: syntax error near `'/example.com''
s.sh: line 1: `if [[ ( ! grep '/example.com' /opt/nfs &>/dev/null ) || ( ! grep -R '/example.com' /data &>/dev/null) ]]'
  • what errors? ... – RomanPerekhrest Oct 10 '17 at 10:50
  • Hu @RomanPerekhrest, I have updated my question with errors. Thanks. – Buvanesh Kumar Oct 10 '17 at 10:53
  • Most probably the use of & in the if statement. Also there is no need to redirect to /dev/null as you can use grep -q (quiet) instead – Raman Sailopal Oct 10 '17 at 11:11
  • Read Simple logical operators in Bash – Gilles Oct 10 '17 at 18:55
3

Straight-forward way:

grep -q '/example.com' /opt/nfs || grep -Rq '/example.com' /data
if [ $? -eq 0 ]; then   # check exit status
    echo "Passed"
else 
    echo "Failed"
fi

  • grep's -q option tells do not write anything to standard output. Exit immediately with zero 0 status if any match is found, even if an error was detected.

  • $? - contains exit status code of the last command run


The above could be also simplified to:

if grep -q '/example.com' /opt/nfs || grep -Rq '/example.com' /data; then
    echo "Passed"
else 
    echo "Failed"
fi
  • Working great. thank you so much for the explanation. – Buvanesh Kumar Oct 10 '17 at 11:52
  • @BuvaneshKumar, you're welcome – RomanPerekhrest Oct 10 '17 at 11:54
  • 3
    [ $? -eq 0 ] is a bit pointless as a command. That's a command that returns a 0 exit status if the previous exit status was 0. Doing if grep.... directly would make more sense. – Stéphane Chazelas Oct 10 '17 at 12:34
  • @StéphaneChazelas, you have my note – RomanPerekhrest Oct 10 '17 at 13:45
5

[[...]] is a construct used to perform comparisons and other sorts of tests. It's a ksh command whose parsing follows special syntax rules and replaces the [ standard command (with normal simple command parsing).

Here, it's of no use. It's whether grep the grep command succeeds that you want to test (not a [[...]] or [ command), so it's just:

if grep -qF /example.com /opt/nfs || grep -RqF /example.com /data
then echo passed
else echo failed
fi

-q suppresses the output and also optimises by exiting as soon as one match is found instead of trying to find all matches.

  • Hi @StéphaneChazelas I would like to try this in a reverse way as follows " if ! grep -q /example.com /opt/nfs || ! grep -Rq /example.com /data then echo failed else echo passed fi" But I didn't get expected output. Is there any wrong with above reverse script? – Buvanesh Kumar Oct 10 '17 at 14:22
  • @BuvaneshKumar, are you sure it's a || and not a && that you meant? Do you want /example.com to be found in neither /opt/nfs nor /data (&&) or either not found in /opt/nfs or not found in data (||)? ! { A || B; } is ! A && ! B – Stéphane Chazelas Oct 10 '17 at 14:38
  • I am sure, it's a | | and not a &&. – Buvanesh Kumar Oct 10 '17 at 15:28
3

Here is a possible simplification of your solution:

  • First of all, if you are using GNU grep, it can search in multiple file|folders provided in argument line. So basically no need to launch two grep command for looking to the same pattern in two different folders : grep '/example.com' /opt/nfs /data does the job for searching occurence of /example.com in those two folders.
  • Second two negations equal a positive. So why not simply use this code : if grep -rq "/example.com" /opt/nfs /data ; then echo "success" ; else echo "failed" ; fi grep will be successfull if it finds occurence of "/example.com" either in /opt/nfs or in /data

It will be faster, and more efficient, only one grep spawned from the shell.

  • Good point. (note that all greps can search in multiple files, it's not just GNU grep; however -r/-R was initially a GNU grep feature and depending on the version both are not necessarily the same). – Stéphane Chazelas Oct 10 '17 at 19:23
  • I was not sure about others grep i only have Gnu version at hand. – netmonk Oct 10 '17 at 20:55
  • After looking again at the OP and my solution, i conclude my solution is not valid. The OP only succeed if /example.com is present in both folder /opt/nfs and /data, it fails in all other situation. grep is unable to handle that in one invocation. – netmonk Oct 10 '17 at 21:53
2

Try like this:

if [[ ! $(grep '/example.com' /opt/nfs &>/dev/null) || ! $(grep -R '/example.com' /data &>/dev/null) ]]
then
echo "Failed"
else
echo "Passed"
fi

But i think your script does not make sense because you suppress stdout and stderr with &>/dev/null. The output of your grep command always will be empty. Replace & to 2 to suppress stderr only.

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.