0

I'm trying to comprehend what are all the possible constructs you can pass to if in bash.

In the GNU reference:

The syntax of the if statement is:

if test-commands; then consequent-commands; [elif more-test-commands; then more-consequents;] [else alternate-consequents;] fi 

The test-commands list is executed, and if its return status is zero, the consequent-commands list is executed...

So I understand that test-commands may be anything that returns a status. So first I thought that this must be one of the followings:

  • the test built-in (i.e. [ ] )
  • The [[ ]] syntax
  • some command (may be any executable)

And as I knew the test command, it has a ! operator (among others) that can inverse the return of the conditional statement you put in it, as such:

if [ ! -z "non-empty" ]; then echo "ok"; fi 

Until then I was happy thinking I know bash. But then I found that I can do:

if ! [ -z "non-empty" ]; echo "Ok!"; fi 

That breaked my heart - I thought that the ! thing belongs to the test command (also to the [[]] syntax) - but what is it outside of it? And why does if takes it?

What construct exactly is ! ? And are there other things acceptable?

8
  • 2
    Here is the manual section where the accepted answer's quote is found: pipelines. The [ ! ... ] exclamation point (part of the syntax of the test command) is a different exclamation point from the ! [ ... ] exclamation point (negation of a pipeline status), and neither are directly tied to if. Commented Oct 4, 2021 at 9:56
  • 1
    ! only has anything to do with test/[ when you use it inside a test expression. The other times it's part of regular shell syntax and usable anywhere (not just in if). See the POSIX sh standard at pubs.opengroup.org/onlinepubs/9699919799/utilities/… specifying the not-test version, and pubs.opengroup.org/onlinepubs/9699919799/utilities/test.html specifying the test version. Commented Oct 4, 2021 at 11:43
  • 2
    There are no specific constructs which can be passed: After if must be a command (and this can be any command). If the command terminates with exit code 0, the then branch is taken; otherwise it's the else part. No fancy syntax here. Commented Oct 4, 2021 at 12:28
  • 1
    what are all the possible constructs you can pass to if in bash you can put anything inside if, you can write the whole script inside if, there are no limits. For example a loop and another expression inside an if: if i=0; while ((i++ < 5)); do ((j=i*2)); done; ((j == 10)); then echo "j=$j"; fi;. The ! is like similar in construct like if or while, it just inverts the exit status of the command (actually whole pipeline). But command ! - ! is just a string, just like in echo if would print if. If the string ! is passed to [ command, then [ reacts in specific way. Commented Oct 4, 2021 at 13:31
  • 1
    what is it outside of it? is it's the first word in the list, it's a negation, if it is not the first word, it's just string ! (but, also except history expansion). why does if takes it? any list of commands takes it ! echo 1, even ! if true; then echo 2; fi What construct exactly is ! ? It's part of pipeline as noted above and And are there other things acceptable? Yes, ! if while case until are basically parsed the same way, see pubs.opengroup.org/onlinepubs/009604499/utilities/… Commented Oct 4, 2021 at 13:34

0

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.