How do I echo stars (*) when reading password with `read`?
Solution 1
As Mark Rushakoff pointed out, read -s
will suppress the echoing of characters typed at the prompt. You can make use of that feature as part of this script to echo asterisks for each character typed:
#!/bin/bash
unset password
prompt="Enter Password:"
while IFS= read -p "$prompt" -r -s -n 1 char
do
if [[ $char == $'\0' ]]
then
break
fi
prompt='*'
password+="$char"
done
echo
echo "Done. Password=$password"
Solution 2
I really liked the answer that Wirone gave, but I didn't like that the backspacing would continue removing characters even back into the "Enter password: " prompt.
I also had some issues where pressing keys too rapidly would cause some of the characters to actually print on the screen... never a good thing when prompting for a password. =)
The following is my modified version of Wirone's answer which addresses these issues:
#!/bin/bash
unset PASSWORD
unset CHARCOUNT
echo -n "Enter password: "
stty -echo
CHARCOUNT=0
while IFS= read -p "$PROMPT" -r -s -n 1 CHAR
do
# Enter - accept password
if [[ $CHAR == $'\0' ]] ; then
break
fi
# Backspace
if [[ $CHAR == $'\177' ]] ; then
if [ $CHARCOUNT -gt 0 ] ; then
CHARCOUNT=$((CHARCOUNT-1))
PROMPT=$'\b \b'
PASSWORD="${PASSWORD%?}"
else
PROMPT=''
fi
else
CHARCOUNT=$((CHARCOUNT+1))
PROMPT='*'
PASSWORD+="$CHAR"
fi
done
stty echo
echo $PASSWORD
Solution 3
read -s
should put it in silent mode:
-s Silent mode. If input is coming from a terminal, characters are not echoed.
See the read
section in man bash
.
Solution 4
I would like to add something to Dennis Williamson's solution:
#!/bin/bash
unset password
echo -n "Enter password: "
while IFS= read -p "$prompt" -r -s -n 1 char
do
# Enter - accept password
if [[ $char == $'\0' ]] ; then
break
fi
# Backspace
if [[ $char == $'\177' ]] ; then
prompt=$'\b \b'
password="${password%?}"
else
prompt='*'
password+="$char"
fi
done
In above example script handles backspace correctly.
Solution 5
I don't know about stars, but stty -echo is your friend:
#!/bin/sh
read -p "Username: " uname
stty -echo
read -p "Password: " passw; echo
stty echo
Deniz Zoeteman
Back-end (web)development. Specialised mostly in PHP.
Updated on July 09, 2022Comments
-
Deniz Zoeteman almost 2 years
What do I need to do for code in Bash, if I want to echo
*
s in place of password characters (or even just hide the characters completely) when the user types something in usingread
? -
SiegeX over 13 yearsYou need to
unset IFS
or addIFS=
to your while loop otherwise your loop will prematurely break on passwords that contain spaces. Also, you should add the-r
flag toread
so that passwords can contain backslashes. -
Brad Mace over 11 years
password+="$char"
didn't work on my system. I had to dopassword="${password}${char}"
instead. -
SourceSeeker over 11 years@BradMace: You must not be using Bash, ksh (93) or zsh or you are using a very old version of Bash (e.g. 2.05b).
-
kratenko almost 10 yearsI'm far from beeing a bash-expert, but I think this code has several issues (like password having a fixed length of 6 and not working with backspaces)
-
Keith Thompson almost 10 yearsThat hardly seems necessary since
read
has a-s
option (the question is taggedbash
so we can assume bash-specific features). Interrupting theread
command (e.g., by typing control-C) could leave the tty in-echo
mode. -
Keith Thompson almost 10 yearsIt handles DEL "correctly". It doesn't do anything special with backspace (Ctrl-H).
-
Wirone almost 10 years"Normal" users rather use standard backspace, not Ctrl+H. Above script does not handle correctly arrow keys too, but hey, it's better to handle backspace and not handle Ctrl+H, or don't handle both? ;)
-
Keith Thompson almost 10 yearsCtrl-H is backspace (the Unicode standard calls it
BACKSPACE
).$'\177'
is DEL (Unicode calls itDELETE
). Some terminal programs may optionally map the Backspace key to the DEL character, but many "normal" users, including myself, map it to the backspace (Ctrl-H) character. A robust solution would examine the user's tty settings. -
Wirone almost 10 yearsI didn't mean Unicode. I said only that for standard user backspace is a key on the keyboard, with "backspace" label ;) And this is what is mapped in script.
-
Keith Thompson almost 10 yearsWhat I wrote applies to Unicode, ASCII, and Latin-N for various values of N.
$'\177'
is theDEL
character; the backspace character is$'\010'
or'\b'
. What "standard" are you referring to? (When I type Ctrl-V Backspace at a shell prompt, it echoes^H
; am I violating some standard?) -
Wirone almost 10 yearsDude, I just refer to
keyboard layout
. I didn't see$'\177'
,$'\010'
nor'\b'
on any button. I didn't mean any standards like ASCII. Backspace is considered to delete char before caret,DEL
- after it, user does not have to know what char/code it sends. EOT. -
Keith Thompson almost 10 yearsDude, the backspace key on my keyboard sends an ASCII BS character (8), not an ASCII DEL character (127). My tty settings are such that typing backspace deletes the character before the cursor. It's configurable, and your code assumes a particular configuration that is not universal. There is nothing non-standard or abnormal about my setup, and your code would not work properly with it.
-
Starfish almost 10 yearsInstead of hardcoding the character for the backspace, add
backspace=$(tput kbs)
before entering the loop and then compare $char against $backspace. That way it'll work no matter what value the user has set their backspace key to send. -
Wirone almost 10 yearsThanks for
tput
, but to be 100% sure it's working we need to know if user hastput
in path, which is not obvious (I didn't have, because I'm using Cygwin and had to installncurses
to get it). Will try to implement it meanwhile ;) -
anthony over 7 yearsA more advance version is ask_password_stars. It was developed as part of my personal notes on Cryptogrphy, Password Input.
-
anthony over 7 yearsA more advance version is ask_password_stars. It was developed as part of my personal notes on Cryptogrphy, Password Input.
-
anthony over 7 yearsHe wants some feedback, not noecho silence!