4

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.

4
  • 1
    You don't have to run the command inside the []'s of an if statement... Jun 8, 2015 at 21:24
  • @AndrewHenle Could you clarify what you mean? Jun 8, 2015 at 21:25
  • 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.... Jun 8, 2015 at 21:45
  • 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. Jun 9, 2015 at 7:00

2 Answers 2

10

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).

6

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
2
  • 1
    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. Jun 9, 2015 at 7:01
  • @Scott Nah, you're right, your solution looks nicer anyway.
    – ferada
    Jun 9, 2015 at 10:13

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .