Main Terminal Window Displaying Commands Only

Solution 1:

I know little about programming languages, but Bash can definitely set up to behave like you want it, so here's how I would do it.

General Setup

Define a function in your ~/.bash_aliases or ~/.bashrc file that allows you to start your command in a new terminal, e.g.

foo () { ( xterm -hold -e bash -c "$*" & ) ;}

This way foo echo bar opens up a new xterm which shows just the output of echo bar, here this would be a window with just the word bar in it. A chain of commands must be quoted, e.g. foo "echo bar && echo baz". You can substitute xterm by the terminal emulator of your choice, but you need to figure out what the stay open option is – read the man page. Option -e should work for all of them. Note that as a function name you can choose even a single symbol like :, _ or · (AltR+,).

Explanations

  • foo () { … ;} – define a function foo which does
  • ( … ) – start in a subshell, this releases the original terminal so that a new command can be executed even when other output terminals are still open
  • xterm -hold -e … – run xterm, run and -hold it open after the command finished
  • bash -c " … " – execute the command(s) , needed for being able to run multiple commands
  • $* – matches every argument of foo = the full chain of commands after foo

Fine-tuning

Closing the output terminal window

You can close the output terminal using your desktop environment's standard shortcut for that – Alt+F4 by default.

If you want the output terminal to stay open for let's say five seconds after the command finished, you need to define the function like so:

foo () { ( xterm -e bash -c "$* && sleep 5" & ) ;}

Replace && by & for the terminal to stay open only until the command is finished, but at least five seconds.

Input facilitation

Using xdotool (ugly and dirty, boo)

It'll bother you to type foo before every single command in your main terminal, so I set up a dirty workaround for that – install xdotool first if necessary. When you open your main terminal, first set this variable:

PROMPT_COMMAND='xdotool type "foo "'

This will automatically type foo followed by a space after, but unfortunately also before every new prompt. All left for you to do is to type your (chain of) command(s).

Using a perl function (massively cool)

The question how to perform the following was asked on Unix.SE and got a brilliant answer by Stéphane Chazelas, whose solution is used here. If this helps you in any way please visit the linked question and upvote his answer.

Add the following lines to your ~/.bashrc file and save it:

insert() { perl -le 'require "sys/ioctl.ph"; ioctl(STDIN, &TIOCSTI, $_) for split "", join " ", @ARGV' -- "$@" ;}
auto_enter() { bind $'"\u200b":"\1'$1' \5"'; PROMPT_COMMAND="insert $'\u200b'" ;}

Now when you open a new terminal and run auto_enter foo, the string “foo ” (with the space automatically added) will appear after every new prompt. If you type something while a command is executed, “foo ” is going to be inserted even before this text.

User-friendly interaction

This version of the function saves the output in a temp file, counts its lines and asks the user whether to display it in a new window:

foo () {
  limit=10 # set line limit
  tf=$(mktemp) # create temp file
  "$@" > $tf # execute command, save output in temp file
  lc=$(wc -l < $tf) # get output's line count
  [ $lc -ge $limit ] && # if line count >= limit then
  ( read -p "The output is $lc lines long, do you want to open it in a new window (y/n)? " yn
    case $yn in
        [Yy]* ) xterm -hold -e "cat $tf" & exit;; # open in new window, send to background and exit
        [Nn]* ) cat $tf; exit;; # print output to stdout and exit
        * ) echo "Please answer yes or no.";; # wrong answer
    esac ) || # else
  cat $tf # print output to stdout
}

Of course this can be highly tweaked and customized, but I think it's a good start.

And Now for Something Completely Different™

A totally different way of achieving your goal is using shell output redirection. who gives you a list of running terminals, e.g.:

> who
username tty7         2017-09-07 20:46 (:0)
username pts/2        2017-09-07 20:47 (:0)
username pts/1        2017-09-07 21:05 (:0)

You can send the output to any of them by simply appending e.g. > /dev/pts/1 to your command, which of course can also be used in a function as shown above.

GNOME Terminal emulator (gnome-terminal) sessions are not displayed by who, nonetheless the pts devices exist equally for them. You can determine open terminal sessions just by trying or with ls /dev/pts | sed '/^[0p]/d' instead.