You could use GNU
screen's vertical split feature:
#! /bin/bash -
tmpdir=$(mktemp -d) || exit
trap 'rm -rf "$tmpdir"' EXIT INT TERM HUP
mkfifo "$FIFO" || exit
cat > "$conf" << 'EOF' || exit
screen -t stderr sh -c 'tty > "$FIFO"; read done < "$FIFO"'
screen -t stdout sh -c 'read tty < "$FIFO"; eval "$CMD" 2> "$tty"; echo "[Command exited with status $?, press enter to exit]"; read prompt; echo done > "$FIFO"'
export FIFO CMD
screen -mc "$conf"
To use for instance as:
that-script 'ls / /not-here'
The idea is that it runs screen with a temporary conf file that starts two screen windows in a vertical split layout. In the first one, we run your command with the stderr connected to the second one.
We use a named pipe for the second window to communicate its tty device to the first one, and also for the first one to tell the second one when the command is done.
The other advantage compared to pipe-based approaches is that the command's stdout and stderr are still connected to tty devices, so it doesn't affect the buffering. Both panes can also been scrolled up and down independently (using
screen's copy mode).
If you run a shell like
bash interactively with that script, you'll notice the prompt will be displayed on the second window, while the shell will read what you type in the first window as those shells output their prompt on stderr.
In the case of
bash, the echo of what you type will also appear on the second window as that echo is output by the shell (readline in the case of
bash) on stderr as well. With some other shells like
ksh93, it will show on the first window (echo output by the terminal device driver, not the shell), unless you put the shell in
vi mode with
set -o emacs or
set -o vi.