0

I have the following if-then block in a Bash function declaration, using grep and a logical OR (||):

if grep -q <somepattern> <file> || grep -q <somepattern> <file2>; then

The above works well, yay!!

But I went to "clean this up" a bit and thought this should be the same, but fails:

if [ grep -q <somepattern> <file> ] || [ grep -q <somepattern> <file2> ]; then

or

if [ grep -q <somepattern> <file> || grep -q <somepattern> <file2> ]; then

I get this error:

-bash: [: missing `]'
grep: ]: No such file or directory

I thought that not using [[ $(<foo>) ]] syntax would be safe and reduce clutter, but it is not clear to me why this does not work. Have googled around a bit and it still unclear to me why this fails.

as an interesting side note, this is ok:

if [ $(grep -q <somepattern> <file>) ] || [ $(grep -q <somepattern> <file2>) ]; then

my thinking was the $(..) wrapping the grep statements is overkill as the [..] would be looking for the return from grep.

I set -x to get some clues and I see this:

+ '[' grep -q <somepattern> <file> ']'
-bash: [: too many arguments
+ '[' grep -q <somepattern> <file2> ']'
-bash: [: too many arguments

My understanding of test leads me to believe this should work, obviously not. Though maybe this has to do with the observation that test will not execute the grep command inside [..] or [[..]] blocks, hence success with grep enclosed in $(..) syntax

Anyone want to shed a bit more light onto this for me?

  • 3
    `[` is not bash syntax at all, it's an alias for the command also named `test`. You should just run `if grep -q`, not `if [ grep -q`. – Charles Duffy Mar 05 '19 at 21:35
  • 1
    ...and just as `foo || bar` runs two simple commands, `foo` and `bar` with a short-circuiting logical OR between them, `[ grep -q || grep -q ]` runs two separate commands, `[ grep -q ` and `grep -q ]`. Because these are separate commands, the `[` before the first one is not matched with the `]` after the second. – Charles Duffy Mar 05 '19 at 21:41
  • Ok thanks! That helps. I stated below, I has a poor understanding of ```test``` ```[``` block. This has helped. Cheers! – oaccamsrazor Mar 05 '19 at 23:01
  • 1
    It's not really a "block" at all; it's just a regular command, treated the same as anything else -- `ls` or `echo` or whatnot -- insofar as parsing is concerned, with the caveat that when it's called under the name `[`, it expects to see a `]` as its final argument. (By contrast, when called under the name `test`, it has no such expectation). – Charles Duffy Mar 05 '19 at 23:03
  • yeah. That has made the difference to me: …it's not really a "block" Years of writing scripts and I just had these baked in conventions I used to make them work, never really bother to understand why, well until now . Thanks again! – oaccamsrazor Mar 05 '19 at 23:12

1 Answers1

1

if simply runs a command, checks if its return code is 0 (true) or anything else (false) before picking a branch to execute.

[ (and test) is simply one possible command for it to run, a very popular and useful command. But it doesn't do what you want in this case. You want something more feature complex, a grep of a file. A grep of two files, potentially, actually.

All you need to do is ensure that the command (singular...ish) you run after if returns 0 in case it results in the behaviour you want to check for, and non-0 otherwise. In your case, grep ... || grep ... returns 0 when you want to run the extra commands, and non-0 otherwise. There is no test functionality that matches this, so you have, more or less, the right idea to start with.

Tanktalus
  • 21,664
  • 5
  • 41
  • 68
  • Ok thanks, this helps my understanding!! I think I need better understanding of ```test```. :). I experimented replacing the ```[..]``` block with ```test``` statements. My confusion seems to be my previous belief that what was inside of a ```test``` or ```[``` block is interpreted like a shell command itself; similar to enclosing the ```grep``` in ```$(..)``` as implied functionality of ```test```, that was my problem, it would need to be more explicit. Thanks again, – oaccamsrazor Mar 05 '19 at 22:59