0

I created the following BASH script that works perfectly for getting a password from the user:

while [ -z "$PASSWORD" ]
do
    echo "Please enter a password:"
    read -s PASSWORD1
    echo "Please re-enter the password to confirm:"
    read -s PASSWORD2

    if [ "$PASSWORD1" = "$PASSWORD2" ]; then
        PASSWORD=$PASSWORD1
    else
        # Output error message in red
        red='\033[0;31m'
        NC='\033[0m' # No Color
        echo ""
        echo -e "${red}Passwords did not match!${NC}"
    fi
done

# This is just here to prove script works
echo "password is: $PASSWORD"

However, if I place it in a function, it stops working:

function getPasswordFromUser()
{
    while [ -z "$PASSWORD" ]
    do
        echo "Please enter a password:"
        read -s PASSWORD1
        echo "Please re-enter the password to confirm:"
        read -s PASSWORD2

        if [ "$PASSWORD1" = "$PASSWORD2" ]; then
            PASSWORD=$PASSWORD1
        else
            # Output error message in red
            red='\033[0;31m'
            NC='\033[0m' # No Color
            echo ""
            echo -e "${red}Passwords did not match!${NC}"
        fi
    done
    echo $PASSWORD
}

PASSWORD=$(getPasswordFromUser)

# This is just here to check if script worked
echo "got password $PASSWORD"

If I change the call to the function from PASSWORD=$(getPasswordFromUser) to: getPasswordFromUser; then the method starts "working" but the password is output to the screen, and I haven't captured it.

Is there a way to update this BASH script so that I can call a function to get a password from the user without the password ever being displayed in the terminal?

  • In case it matters, this is for Debian/Ubuntu.
Programster
  • 12,242
  • 9
  • 49
  • 55

3 Answers3

2

If you call the function like myvar=$(myfunction) it will catch the first echo statement.

What you can do, instead, is to define a variable within the function and then access it. There is no scope in bash, so you will be able to access it once the function has been executed.

See an example on each one of them:

$ cat a
#!/bin/bash

function myf()
{
echo "heeeiiii"
echo "hellO"

}

function myf2()
{
echo "lets define var MYTEST"
MYTEST="this is my test"
}

r=$(myf)

echo "this is myf: $r"

echo "MYTEST=$MYTEST"
myf2
echo "MYTEST=$MYTEST"

Execution:

$ ./a
this is myf: heeeiiii
hellO
MYTEST=
lets define var MYTEST
MYTEST=this is my test
fedorqui
  • 275,237
  • 103
  • 548
  • 598
  • 1
    Thanks! The key point there being: `There is no scope in bash, so you will be able to access it once the function has been executed` so I can just run `getPasswordFromUser;` and `PASSWORD` will be set outside the function. No need to echo PASSWORD inside the function and try to capture it. – Programster Dec 03 '14 at 13:55
1

Most of the output in your function should be written to standard error, not standard output.

getPasswordFromUser()
{
    while [ -z "$PASSWORD" ]
    do
        echo "Please enter a password:" >&2
        read -s PASSWORD1
        echo "Please re-enter the password to confirm:" >&2
        read -s PASSWORD2

        if [ "$PASSWORD1" = "$PASSWORD2" ]; then
            PASSWORD=$PASSWORD1
        else
            # Output error message in red
            red='\033[0;31m'
            NC='\033[0m' # No Color
            echo -e "\n${red}Passwords did not match!${NC}" >&2
        fi
    done
    echo "$PASSWORD"
}

Also, be sure to quote $PASSWORD in the final line; someone may use multiple runs of whitespace or shell glob characters in their password!

chepner
  • 497,756
  • 71
  • 530
  • 681
0

Your first attempt is correct:

~$ PASSWORD=$(getPasswordFromUser)
~$ echo $PASSWORD
Please enter a password: Please re-enter the password to confirm: a

You just don't see the "Please enter a password" because it is captured by the $(..).

You have several possibilities:

  • use a global variable
  • use different descriptor
  • have the function take a variable as the first arg and modify the variable with the string you want to return.

Some examples can be found in how to return a string value from a bash function, the Advanced Bash-Scripting Guide, or the linux journal.

Community
  • 1
  • 1
fredtantini
  • 15,966
  • 8
  • 49
  • 55