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

9

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

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.