I'm writing a custom startup command for gnome-terminal, and my intention is to display a welcome message every time I launch it.

The message displays correctly, I coded it in order to make the letters appear one by one in a time rate of 0.09s:

echo -n "W" 
sleep 0.09
echo -n "e" 
sleep 0.09
echo -n "l"
sleep 0.09
echo -n "c"
sleep 0.09
echo -n "o"
sleep 0.09 
echo -n "m"
sleep 0.09 
echo -n "e" 
sleep 0.09 

While testing it, I thought it would be quite comfortable to be able to stop the letters from appearing and start su directly. I came up with the following solution:

su --command "read -n 1 -s key; if [[ "$key" == "g" ]]; then echo "Test Successful."; else echo "Test Failed."; fi;"

I have to use su -c if I don't want bash to get angry and throw an illegal action: read -n. This code snippet is for debugging purposes exclusively, as I wanted to test how does bash read the one-line command combination.

The main problem comes when I try to execute this code from the config file (the one where I write my custom command for startup). Bash returns:

No passwd entry for user 'Successful.; else echo Test'

Mysteriously, when I try the same command (without su -c ) in the default profile it works perfectly, but if I try it with su -c, it doesn't.

Trying with other commands in the default profile, I typed su -c "echo Hi" and worked fine. Why could be this happening? Do you have any idea?


Enclose the whole command in single quotes instead of double. First thing to note is you have a variable ($key). Enclosed in double quotes, it will be substituted by the shell before making it an argument given to su. Second thing is regarding quote matching what you currently have, with double quotes, the argument will be split like this:

  • arg0: su
  • arg1: --command
  • arg2: read -n 1 -s key; if [ <value of $key or nothing> == g ]; then echo Test
  • arg3: Successful.; else echo Test
  • arg4: Failed.; fi;

Enclosing the whole args in single quotes allows fixes the two issues, avoid variable substitution and fixes the split weirdness, by passing this string as-is as the second argument of su.

Bonus: as a general note, avoid double brackets for tests when possible, it's a bashism (syntax that only work with bash and could be replaced by a more compatible counter part)

The following version should work as expected.

su --command 'read -n 1 -s key; if [ "$key" == "g" ]; then echo "Test Successful."; else echo "Test Failed."; fi;'
|improve this answer|||||
  • Alright, it works. Thank you so much! But now I need the function to work while the 'echoes' work, like if it was executing in background. Any clue? – xvlaze Jan 30 '16 at 22:50
  • You can background the commands that echoes by surrounding them with parentheses and putting it in back ground with a &. This might messup the display if you write during it ;) ex: (echo foo; sleep 1; echo bar)& – Damien Feb 1 '16 at 8:37
  • And how should I do if I want the read command work at the same time as the echoes, and stop them if I press any key? I've tried with your answer, but it's not giving me the proper results. What I would like is to turn "echo: "Test..." into a su command that stop echoes and starts a command line, but I get: "bash: cannot set terminal process group (3700): Inappropriate ioctl for device". The command itself is: "(su --command 'read -n 1 -s key; if [ "$key" == "g" ]; then su; fi;') &" – xvlaze Feb 2 '16 at 17:47

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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