I would like to run a script that detects the current terminal and generates a new terminal window, in the background, with a shell command (e.g. htop)

I get the desired outcome at the command line:

cterminal="$(ps -p $(ps -p $$ -o ppid=) o args=)"  
$(echo $cterminal -e "htop")&  

and works on all terminals. But not from a script:

cterminal="$(ps -p $(ps -p $$ -o ppid=) o args=)"  
echo $cterminal  
"$cterminal" -e "htop" &  

current script output:

$ bash script.sh
$ /usr/bin/htop: /usr/bin/htop: cannot execute binary file

Any hints?

1 Answer 1


Your ps command is printing the PID of the parent process (PPID). When you are running a terminal emulator, $$ (the current process's PID) will be pointing to your shell session and its PPID will be the terminal emulator that launched it.

Scripts are run in their own subshells. This means that the parent process of a script is the shell that launched it. So, when you run your command, you are not executing xterm -e htop but bash xterm -e htop. To illustrate:

$ bash top  
/sbin/top: /sbin/top: cannot execute binary file

You can test this by running echo $(echo $cterminal -e "htop") from a script and from the commandline.

To run the script from a GUI terminal emulator, you could use the PPID's PPID instead:

cterminal="$(ps -p $(ps -p $PPID -o ppid=) o args=)"  

Finally, don't use $(echo ...) to run your command, just run it:

#!/usr/bin/env bash
$(ps -p $(ps -p $PPID -o ppid=) o args=) -e top
  • this makes a lot of assumptions about the environment - particularly about a bash's granddaddy necessarily being a terminal emulator. there's also the IFS/glob deal where just running it is concerned.
    – mikeserv
    Commented Dec 11, 2015 at 5:52

You must log in to answer this question.

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