1

I want to read a user's password securely within the execution of a curl command. A made a basic proof of concept which mostly works, but the output of the echo command is coming on the same line as the "Password" prompt and I am trying to find a way to put it on a new line. When I run the command, the "Password: " prompt is printed, I type "test" and then the echo command returns with "test" filled in on the same line. How do I get it to print the echo command on a new line?

Am doing this with the following ouput

$ echo "this is a $(read -e -s \?"Password: ")"
Password: this is a test

What I want is a way to do the echo command above but get the following output when I type "test" for the password

$ echo "this is a $(read -e -s \?"Password: ")"
Password: 
this is a test

One thing I tried was echoing a newline after reading the password, but that didn't work. You can see in the second one that the echo command is printing after the echo command. It is almost like the first echo starts, waits for the subprocess to return something, then completes, then the second echo runs. I am not sure how this ordering is determined and if there is a way to force the echo in the subprocess to run first.

$ echo "this is a $(read -e -s \?"Password: " && echo -e '\n')"
Password: this is a test
$ echo "this is a $(read -e -s \?"Password: " && echo 'hello world')"
Password: this is a test
hello world

I am doing this on macOS Ventura 13.1 with zsh 5.8.1.

1 Answers1

0

It seems that you just placed the newline \n at the wrong place. You should get the desired output with this command:

$ echo -e "\nthis is a $(read -e -s \?"Password: ")"

What I think is happening:

  • The argument of echo includes a command substitution, so the shell needs to span a subshell first, to compute the complete argument, i.e. the read command is executed first, printing "Password: "
  • Since you told read to not echo (-s) the user input to the terminal, the "cursor" remains at the end of the read prompt, even you press Enter at the end.
  • Now the echo command is ready to be executed, and this will happen next.
  • So, you need to start with a newline character, to get to a new line and then print the desired string. At the end a newline character is appended automatically as this is echo's default behavior.

Just as a remark, echo -e is not portable (see e.g. https://unix.stackexchange.com/q/88307/33390), so you should consider one of these options instead:

  • Use the shell expansion $'\n' to get a newline character:

    $ echo $'\n'"this is a $(read -e -s \?"Password: ")"
    
  • Omit echo altogether and use printf; note that you now need also a trailing \n:

    $ printf "\nthis is a $(read -e -s \?"Password: ")\n"
    
mpy
  • 28,816