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

Sign up to request clarification or add additional context in comments.

2 Comments

+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]"
@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.
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 Comments

You could use declare -u choose; read choose instead of nocasematch. Nice call using a default value in the expansion.
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. :)
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.

Comments

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.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.