8

I am trying to automate our application backup. Part of the process is to check the exit status of egrep in an if statement:

if [ ! -f /opt/apps/SiteScope_backup/sitescope_configuration.zip ] || [ egrep -i -q "error|warning|fatal|missing|critical" "$File" ] then echo "testing" fi 

I expected it to output testing because the file exists and egrep returns success, but instead I'm getting an error:

-bash: [: too many arguments 

I tried with all kinds of syntax - additional brackets, quotes etc but error still persists.

Please help me in understanding where I am going wrong.

4
  • @DavidGrayson: that doesn't mean it "works". Commented Apr 2, 2016 at 9:03
  • egrep shouldn't be surrounded with brackets. Commented Apr 2, 2016 at 9:08
  • 1
    David : try it with -f on a file that exists in your system, and you will get the same error than Abhinandan. Commented Apr 2, 2016 at 9:08
  • Thanks ALL for your reply. @kichik - Removing brackets around egrep worked.. Thanks much:) Commented Apr 2, 2016 at 9:33

1 Answer 1

25

You are making the common mistake of assuming that [ is part of the if statement's syntax. It is not; the syntax of if is simply

if command; then : # ... things which should happen if command's result code was 0 else : # ... things which should happen otherwise fi 

One of the common commands we use is [ which is an alias for the command test. It is a simple command for comparing strings, numbers, and files. It accepts a fairly narrow combination of arguments, and tends to generate confusing and misleading error messages if you don't pass it the expected arguments. (Or rather, the error messages are adequate and helpful once you get used to it, but they are easily misunderstood if you're not used.)

Here, you want to check the result of the command egrep:

if [ ! -f /opt/apps/SiteScope_backup/sitescope_configuration.zip ] || egrep -i -q "error|warning|fatal|missing|critical" "$File" then echo "testing" fi 

In the general case, command can be a pipeline or a list of commands; then, the exit code from the final command is the status which if will examine, similarly to how the last command in a script decides the exit status from the script.

These compound commands can be arbitrarily complex, like

if read thing case $thing in '' | 'quit') false;; *) true;; esac then ... 

but in practice, you rarely see more than a single command in the if statement (though it's not unheard of; your compound statement with || is a good example!)

Just to spell this out,

if [ egrep foo bar ] 

is running [ aka test on the arguments egrep foo bar. But [ without options only accepts a single argument, and then checks whether or not that argument is the empty string. (egrep is clearly not an empty string. Quoting here is optional, but would perhaps make it easier to see:

if [ "egrep" ]; then echo "yes, 'egrep' is not equal to ''" fi 

This is obviously silly in isolation, but should hopefully work as an illustrative example.)

The historical reasons for test as a general kitchen sink of stuff the authors didn't want to make part of the syntax of if is one of the less attractive designs of the original Bourne shell. Bash and zsh offer alternatives which are less unwieldy (like the [[ double brackets in bash), and of course, POSIX test is a lot more well-tempered than the original creation from Bell Labs.

Sign up to request clarification or add additional context in comments.

6 Comments

This is an adaptation of this earlier answer of mine to a vaguely similar question.
Nit pick: the if syntax is actually if list of commands; then and the last command determines the status. And a command may be a pipe.
@Jens Thanks, very astute! Updated.
Can anyone explain me why in other languages 0 is considered a false (and other numbers true) and instead here 0 is considered as a truthy value? thank you
@silvanasono Quick googling gets me Why 0 is true but false is 1 in the shell?
|

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.