Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
221 views
in Technique[技术] by (71.8m points)

Checking the success of a command in a bash `if [ .. ]` statement

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.

Question&Answers:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

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.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...