NOTE: st is the actual name of the terminal emulator in my question - https://st.suckless.org/.

I want to create a shortcut that if pressed, pops up st and displays the translation of the word in the clipboard.

I tried using this, but is exits immediately and gives an error:

$ st -e "trans $(xclip -o) -t en; read"`
child finished with error '256'

But the same works with xterm just as expected:

$ xterm -e "trans $(xclip -o) -t en; read"

Using only one command as the -e option of st works, but I need to execute read or something like that after trans so the terminal won`t close immediately.

Is this a bug in st or am I doing something wrong?

  • Oh god another terminal - st.suckless.org – slm Aug 8 '18 at 10:31
  • It did actually already clarify that in the question title, @slm. – JdeBP Aug 8 '18 at 10:35
  • @JdeBP - I don't know if that's a euphemism or what. I've never heard of this terminal before in 30+ yrs. The project's about shows it as ~10yrs (2008). – slm Aug 8 '18 at 10:37
  • I have; and we've had questions dealing with it for over half that time. example example example – JdeBP Aug 8 '18 at 10:50
  • @JdeBP - 4 out of 145k is backing up my position 8-). I mean no disrespect to the project, I just hadn't ever heard of it, and assumed, perhaps incorrectly that others would be in the same boat as I. – slm Aug 8 '18 at 10:54

The -e option is a compatibility mechanism in simple terminal. The command and arguments that you pass, with or without -e, are executed directly, by simple terminal forking and then running execvp() in the child process on exactly the command and arguments it is given. There's no shell involved, and the arguments passed to st are sent on exactly as-is to the target program.

You have passed everything all as one argument. So simple terminal is actually trying to run a command named, literally, trans $(xclip -o) -t en; read (if single quoted, or that modified by whatever the result of the expansion is if you use double quotes). Obviously, you have no command named that.

To use a shell command line — such as you have here with expansions, shell built-in commands, and shell command syntax — you have to explicitly invoke a shell to understand it:

st -e sh -c 'trans "$(xclip -o)" -t en; read'

This runs st which starts an sh shell which runs a short shell script, which contains your commands.


Looking at the man page for st:

st [-aiv] [-c class] [-f font] [-g geometry] [-n name] [-o iofile] [-T title] 
[-t title] [-l line] [-w windowid] [[-e] command [arguments...]]

-e command [ arguments ... ]
      st executes command instead of the shell.  If this is used it must be 
      the last option on the command line, as in xterm / rxvt. This option 
      is only intended for compatibility, and all the remaining arguments 
      are used as a command even without it.

I would agree with @Kusalananda that this switch is only intended to take a single command and nothing as complex as what you're trying to perform.

So for this you need to pass a shell in as the -e argument to st and then pass your commands in as a secondary set of arguments to the more capable shell:

$ st <other args> -e sh -c '....'
$ st <other args> -e bash -c '....'


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.