Given a text message, I need to programmatically generate a bash command to open terminal emulator and show this text in it.
For example, for HelloWorld input string I need to return the following output string:
gnome-terminal -e "$SHELL -c echo\ HelloWorld;exec\ $SHELL"

The problem is that my input messages may consist of arbitrary symbols.
By trial and error, I have ascertained that different symbols are required to be escaped different number of times:

"A" must be converted to "A"        (0 times to be escaped)
" " must be converted to "\ "       (1 times to be escaped)
"(" must be converted to "\\\("     (2 times to be escaped)
"\" must be converted to "\\\\\\\\" (3 times to be escaped)

For example, \(o o)/ must be inserted in the command as \\\\\\\\\\\(o\ o\\\)\\\/: gnome-terminal -e "$SHELL -c echo\ \\\\\\\\\\\(o\ o\\\)\\\/;exec\ $SHELL"

Actually, I don't know bash at all, so I don't have full understanding of the logic behind that.
Could you please tell me the general rule: how to convert any symbol from ASCII subset (10,32-126)?

To bring more clarity on what I'm doing.

I'm trying to write a function (in some programming language) that receives a string InputText and returns another string, which is a correct bash command.
Currently, I'm trying to implement this function as simple concatenation of:
1) constant prefix gnome-terminal -e "$SHELL -c echo
2) inner part which depends on InputText
3) constant suffix ;exec\ $SHELL"
The problem is with the inner part. I'm trying to calculate it as concatenation of each InputText's symbol converted. But I don't know how to convert arbitrary symbol.

Edit 2:
Thanks to choroba for the idea of using single quotes to avoid mass escaping.
I've learned a lot about bash. ))

This is a modified version of choroba's answer.
The same idea, but without "backslashies backslashes tandems", implemented in Lua:

function run_terminal(text)
   local function q(s) return "'"..s:gsub("'","'\\''").."'" end
      'gnome-terminal -e "$SHELL -c "'..q(q("echo "..q(text)..";exec $SHELL"))
run_terminal "Some Text"

Edit 3:
Thanks to Gilles for mentioning "-x COMMAND" option of gnome-terminal. Quoting is not required with this option, so we can reduce level of quoting inside generated commands:

function run_terminal(text)
   local function q(s) return "'"..s:gsub("'","'\\''").."'" end
   os.execute("gnome-terminal -x sh -c "..q("echo "..q(text)..";exec $SHELL"))
run_terminal "Some Text"

2 Answers 2


Quote the string, and you'll only have to backslash the quotes. If you quote twice, you need to escape both quote types.

Update: Gnome terminal needs triple quoting. Just escape the single quotes twice in the string, and use quoted single quotes around the inserted string. You need to backslash the backslashes in the original string, too.

Proof: I used the following Perl script:

use strict;
use warnings;
use feature qw{ say };

chomp( my $msg = <> );
$msg =~ s/\\/\\\\/g;           # Quis backslashies backslashes tandem?
$msg =~ s/'/'\\''/g for 1, 2;  # Replace ' by '\'' twice.
$msg =~ s/"/\\"/g;             # Backslash double quotes.
system q(gnome-terminal -e 'bash -c "echo '\\'') . $msg . q('\\''; exec bash"');
  • Doesn't work for me: the command gnome-terminal -e "$SHELL -c echo\ \"\\(o o)/\";exec\ $SHELL" fails. Apr 4, 2016 at 14:35
  • @EgorSkriptunoff: Where are the single quotes?
    – choroba
    Apr 4, 2016 at 14:36
  • It does not work with single quotes too: gnome-terminal -e "$SHELL -c echo\ '\\(o o)/';exec\ $SHELL" fails. Apr 4, 2016 at 14:50
  • @EgorSkriptunoff: Ah, ok, you want to quote twice. Check the update.
    – choroba
    Apr 4, 2016 at 15:01
  • I need to include text (as immediate string) into the command. Your example takes the string from environment variable, but where is corresponding bash command to save text into that variable? Apr 4, 2016 at 15:12

Forget quoting and put the text in an environment variable.

Use -x to launch a shell.

Don't craft code for $SHELL: you don't know what syntax it understands. Run code in sh, and call $SHELL to invoke an interactive shell.

message='HelloWorld' gnome-terminal -x sh -c 'printf %s\\n "$message"; unset message; exec "$SHELL"'
  • What do you mean by saying "Don't craft code for $SHELL: you don't know what syntax it understands."? Does -c option not portable? Or does echo 'single-quoted text' behave differently across platforms? Or does exec may not work as expected? Apr 5, 2016 at 12:56
  • @EgorSkriptunoff $SHELL doesn't have to be a Bourne-like shell. It could be screen, irb, … anything. It's not a matter of platforms, it's a matter of user choice. Call sh, it behaves the same everywhere (for core functionality). Apr 5, 2016 at 13:29
  • Do you want to say that $SHELL does not have to implement superset of sh features? Apr 5, 2016 at 13:34
  • @EgorSkriptunoff Yes, $SHELL could be anything, it does not have to be related to sh in any way. It's whatever the user wants to use as an interactive shell. Apr 5, 2016 at 13:35
  • Your solution introduces rather serious problem: you may occasionally erase the content of $message env var which may be of importance for other programs invoked by user inside this terminal window. What would you suggest to solve it? Should I use GUID as env variable name? Apr 5, 2016 at 13:39

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .