Simultaneously check for empty output and successful exit status

7,479

Solution 1

First of all, while they are functionally equivalent, $(…) is widely considered to be clearer than `…` — see this, this, and this.  Secondly, you don’t need to use $? to check whether a command succeeded or failed.  My attention was recently drawn to Section 2.9.1, Simple Commands of The Open Group Base Specifications for Shell & Utilities (Issue 7):

A "simple command" is a sequence of optional variable assignments and redirections, in any sequence, optionally followed by words and redirections, terminated by a control operator.

When a given simple command is required to be executed …
                          ⋮                                                                                (blah, blah, blah …)

If there is a command name, execution shall continue as described in Command Search and Execution.  If there is no command name, but the command contained a command substitution, the command shall complete with the exit status of the last command substitution performed.  …

For example,

  • the exit status of the command

    ls -ld "module_$(uname).c"
    

    is the exit status from the ls, but

  • the exit status of the command

    myfile="module_$(uname).c"
    

    is the exit status from the uname.

So ferada’s answer can be streamlined a bit:

if output=$(/etc/grub.d/30_os-prober)  &&  [ -z "$output" ]
    # i.e., if 30_os-prober successfully produced no output
then
    install_linux_only
else
    install_dual_boot
fi

Note that it is good practice to use all-upper-case names only for environment variables (or variables to be visible throughout the script).  Variables of limited scope are usually named in lower case (or, if you prefer, camelCase).

Solution 2

You can assign the value to a variable and then check the exit status as well:

PROBE_VALUE=`/etc/grub.d/30_os-prober`

if [ "$?" -eq 0 ] && [ -z "$PROBE_VALUE" ]; then
    install_linux_only
else
    install_dual_boot
fi
Share:
7,479

Related videos on Youtube

200_success
Author by

200_success

Former moderator of https://codereview.stackexchange.com

Updated on September 18, 2022

Comments

  • 200_success
    200_success over 1 year

    I'd like to write the following test in an installer script1:

    if [ -n "`/etc/grub.d/30_os-prober`" ]; then
        install_dual_boot
    else
        install_linux_only
    fi
    

    However, it's also possible that 30_os-prober produces no output because it somehow failed to complete. If 30_os-prober fails with a non-zero exit status, it would be safer to assume the a dual-boot situation.

    How can I check that 30_os-prober produced no output successfully?

    Basically, I would like to obtain an effect similar to…

    if [ -n "`/etc/grub.d/30_os-prober`" ]; then
        # Do stuff for a dual-boot machine
        install_dual_boot
    elif ! /etc/grub.d/30_os-prober >/dev/null; then
        # OS probe failed; assume dual boot out of abundance of caution
        install_dual_boot
    else
        install_linux_only
    fi
    

    … but without running the same command twice.


    1 Background information: 30_os-prober comes with GRUB2, and the script I am writing is part of my custom configuration for FAI.

    • Admin
      Admin almost 9 years
      You don't have to run the command inside the []'s of an if statement...
    • Admin
      Admin almost 9 years
      @AndrewHenle Could you clarify what you mean?
    • Admin
      Admin almost 9 years
      You need the exit status and the output. You can't get both if you constrain yourself to running the command inside []'s. As ferada's answer shows....
    • Admin
      Admin almost 9 years
      Your question is inconsistent: the first code block says if [ -z … ] then install_dual_boot but the second one says if [ -n … ] then install_dual_boot.
  • Scott - Слава Україні
    Scott - Слава Україні almost 9 years
    Your approach and logic are good, but you seem to have your then and else branches backwards: based on his words and his second code block, the OP seems to want install_dual_boot if the output is -n or the probe fails.
  • ferada
    ferada almost 9 years
    @Scott Nah, you're right, your solution looks nicer anyway.