0

I have a function foo and a variable bar. I want to write a bash conditional that checks that bar is set and that foo returns positive.

I understand that you can write the two conditions as

if [ -z "$foo"]

and

if foo $myparam1 $myparam2

How can I combine these into a single expression? Something like

if [-z "$foo" -a $(foo $myparam1 $myparam2) != '1']

nao
  • 1,128
  • 1
  • 14
  • 37
  • The `-a` argument to `test` (the command also known as `[` -- it's not shell syntax) is marked obsolescent in the current version of the POSIX standard, and shouldn't be used in new code. See https://pubs.opengroup.org/onlinepubs/9699919799/utilities/test.html, particularly the `OB` markers. – Charles Duffy Oct 25 '19 at 20:21
  • `[` is an external command (usually a link to `/bin/test`). In order to work it needs to be a separate word. Also `]` needs to be a separate word. – axiac Oct 25 '19 at 20:26
  • 1
    @axiac, ...well -- *usually* there's a builtin implementation used in preference to the external one as a performance optimization. It's parsed the same way as an external command would be, though. See `type [`, which on stock bash returns *`[ is a shell builtin`*. – Charles Duffy Oct 25 '19 at 20:27
  • @nao, ...btw, notice how in my answer I write `[ -z`, not `[-z`? Just like other command names, you need a space separating the command and its first argument; just as it needs to be `ls -l` instead of `ls-l`, it needs to be `[ -z`, not `[-z`. – Charles Duffy Oct 25 '19 at 20:29

1 Answers1

2

Use && to do a logical-AND of the result of multiple commands:

if [ -z "$foo" ] && foo "$myparam1" "$myparam2"; then

[ is a command[1]. foo is a different command. [ ... && foo ... (written thus because ] is just an argument to the [ command, not any kind of special syntax) is a compound command that has a truthy result only if both [ and foo both have truthy results.


[1] - Your shell is likely to have a built-in implementation as a performance optimization rather than relying on /bin/[ or /usr/bin/[, but at a language level it's parsed the same as anything else.

Charles Duffy
  • 280,126
  • 43
  • 390
  • 441
  • What if the command (foo) is a pipeline? Like foo | bar? How could I have that evaluate in the conditional? – nao Oct 25 '19 at 20:29
  • @nao, *what about* if it's a pipeline? `[ -z "$foo" ] && foo | bar` is a valid compound command. (Whether it's a compound command that does what you want, by contrast, would require you to provide more details about what the behavior you expect is). – Charles Duffy Oct 25 '19 at 20:30
  • `foo "$myparam1" "$myparam2"` is a (degenerate) pipeline; it just consists of a single command rather than two or more commands joined by a pipe. `&&` joins pipelines. – chepner Oct 25 '19 at 20:31