3

Some may have found out that in Ubuntu when you install or update via terminal

you get a question similar to

"do you with to install or remove package [Y/n]?"

when you press enter its like its the same as when you type "Y" or "y"

So i was wondering how to make that in bash This is what i have so far?

echo "question?[Y/n]"
read choose
if [ $choose ~= "Y" ] [ $choose ~= "y" ] [ $choose ~= "" ]
then 
#code
fi

4 Answers 4

8

Classically (meaning it will work in POSIX-ish shells other than bash), you'd write:

echo "Question? [Y/n]"
read choose
if [ "$choose" = "Y" ] || [ "$choose" = "y" ] || [ -z "$choose" ]
then 
    # code
fi

The quotes ensure that the test operator see an argument even if $choose is an empty string.

The [[ operator seems to allow you to get away without quoting strings, but is not part of a POSIX shell. POSIX recognizes its existence by noting:

The following words may be recognized as reserved words on some implementations (when none of the characters are quoted), causing unspecified results:

[[    ]]    function    select

If you want the shell to leave the cursor on the same line as the prompt, you can use:

printf "Question? [Y/n] "

POSIX shells recognize the \c escape; bash does not:

echo "Question? [Y/n] \c"

(There may be a way to make bash handle that, but printf is probably more portable.)

2
  • +1 for printf suggestion. It is much neat compared to echo (personal opinion) :) "echo -n" would print the message and leave the cursor on the same line, e.g. echo -n "Question? [Y/n]" Commented Sep 18, 2012 at 12:32
  • @AshishKumar: Thanks. I remembered that bash follows the Unix 7th Edition Bourne shell using echo -n after I'd posted the answer, instead of the System III, System V style of escape with \c. See Bloated echo command for a discussion about styles of the echo command. Commented Sep 18, 2012 at 13:51
3
echo -n "Question? [Y/n]"
read choose 
shopt -s nocasematch
if [[ "${choose:=Y}" =~ Y ]]; then
     # they said yes
else
     # they said something else
fi

This approach has the possible advantage that it leaves $choose set to Y if you examine it later. If you prefer to be able to tell later whether they entered Y or just pressed enter, you can use ${choose:-Y} instead.

If you'd rather not set nocasematch, you can always check explicitly for both Y and y. Or, if you like the nocasematch solution but care about preserving the state of the flag, you can check and restore it:

shopt -q nocasematch
let not_set=$?
shopt -s nocasematch

...

if (( not_set )); then
   shopt -u nocasematch
fi
2
  • You could use declare -u choose; read choose instead of nocasematch. Nice call using a default value in the expansion. Commented Sep 18, 2012 at 0:34
  • True, but declare -u is a bash-4-ism, and that's not universal (Lion still has bash 3, for instance; not sure about Mountain Lion). IMO, it's silly that it took this long since ksh had typeset -L and -U back in 1983, but there you go. :)
    – Mark Reed
    Commented Sep 18, 2012 at 10:32
2

See test(1).

[ "$choose" = "Y" -o "$choose" = "y" -o "$choose" = "" ]

You must put the variable between double quotes, otherwise the expressions would produce an error with an empty variable, because their respective left sides would be empty.

1

"read" reads input up to enter. So if you want just "enter" to be accepted as answer, try with "" answer. You can use [[ ]] instead of "test" command to check strings ( man test )

dtpwmbp:~ pwadas$ [[ -z "" ]] && echo yes 
yes
dtpwmbp:~ pwadas$ [[ -z "ABCD" ]] && echo yes 
dtpwmbp:~ pwadas$ 

Here, a test for zero-length of the string.

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