There are multiple questions about this sprinkled around the network, but what I could find has one of two things in common:

  • They give the manual solution, which only prints the current running program (with no arguments)
  • The use zsh preexec feature (though I am not sure how that interacts with screen). I am looking for a Bash solution.

How do I get my screen title to show the entire command run, so if I run 3 long running Python scripts for example, I can see the script names in the title as well? For bonus points, if I can get this to keep displaying the last command run that would be even better.

My current setup:

  • export PROMPT_COMMAND='/bin/echo -ne "\033k\033\0134"'
  • PS1 ends with >
  • shelltitle ">|bash"

I tried:

  • Adding stuff between \033k and \033 - breaks with ${BASH_COMMAND}
  • Using trap debug to set an external additional title since for XTERM with no screen I know the solution. This breaks badly with the PS1.

and variations of the above. I want a solution to be through screen, so both the window title and the screen window list show the full command.

As a bonus, I would really like it if Screen interacts nicely with Vim, so changing buffers/opening new files/etc. would dynamically updated in the screen title.


using PROMPT_COMMAND='/bin/echo -ne "\033k\033\0134"' in .bashrc togerther with shelltitle '$ |bash' in .screenrc works fine for me. Using this specific PROMPT_COMMAND somehow breaks my PS1 so i also added the following to .bashrc:

case "$TERM" in
    screen*) PROMPT_COMMAND='/bin/echo -ne "\033k\033\0134"';;

Example image attached - running sleep in window 0, find in window 1, watch in window 2, ping in window 3 and bash in window 4. enter image description here

  • Thanks for the input. Have a look at the screen selection window- are there arguments displayed? The fact you only see find for example is my problem. Suppose I am finding two things on two different screens. I would like to be able to tell them apart when selecting. – kabanus Jan 25 '20 at 6:41
  • As such, I would like to see find /path -name... etc. – kabanus Jan 25 '20 at 6:42
  • Well i did miss that you also wanted to see all the arguments of the commands in your original post. You could try to create some wrappers for your scripts just to overcome limitation of window naming, but that's not ideal. I found a link that migth help. The picture in the link looks at least a bit promising in my opinion. – lager Jan 25 '20 at 12:44
  • I failed to make tap debug work because I did not enclose it in an if, and it interacted badly with PROMPT_COMMAND. You hit the jackpot!! Thanks, you get the credit - I edited the proper answer in, please confirm it for the benefit of future visitors. – kabanus Jan 26 '20 at 9:03
  • @Isaac while my edit did deviate from original intent, this is not an answer currently. The OP did provide the way to a solution and all you are doing is denying them some reputation. I think it would have been more beneficial if you allowed lager to choose to accept or decline. As it stands, I have to remove the accepted mark. – kabanus Jan 27 '20 at 9:07

An year later, here is my solution, using traps. This display the hostname, corrent PWD and command (and screen stuff if on screen). This is easily customized in set_screen_window below. Everything should sit in your .bashrc.

First some helper function to check if I'm on screen or not:

if [[ "$TERM" == "screen"* ]]; then
    screen_title_slicer() { echo "${1:0:40}"; } # Arbitrary cut off. use echo $1 for full.
    screen_title_slicer() { echo "${1//[^[:print:]]/}"; }

The meat of building the command, relying on the useful BASH_COMMAND. I do some custom stuff for fg (such as displaying the original command) and cd (to get real directory):


set_screen_window() {
    [ -z "$title_string" ] && title_string=$(screen_title_slicer "$BASH_COMMAND")
    [ "$title_string" = "fg" ] && read -ra job < <( jobs %% 2> /dev/null )
    [ "$title_string" = "fg " ] && read -ra job < <(jobs "${title_string:3} 2> /dev/null")
    if [ ${#job[@]} -gt 0 ]; then
        title_string=$(screen_title_slicer "${job[2]}")
    if [ "${title_string::3}" = "cd " ]; then
        cwd=$(  eval cd "$(awk '{print $2}' <<< "$BASH_COMMAND")" &> /dev/null && pwd)
        [ -z "$cwd" ] && cwd=$PWD
    [ "$title_string" = "cd" ] && title_string=$ready && cwd=$HOME
    printf "$screen_title_format" "$HOSTNAME -- ${cwd//$HOME/\~}> $title_string" > "$(tty)"
    unset job
    unset title_string

Now initialize the terminal head with my ready string, and trap both error and debug to update the terminal window:

set_screen_window "$ready"
trap "set_screen_window $ready" ERR
trap set_screen_window DEBUG

Finally, in .vimrc we have vim specific stuff:

function! Filename()
    if @% == ""
        return "noname"
    let is_tracked=system("git ls-files " . expand("%"))
    if is_tracked == ""
        return expand("%:t")
    return gitbranch#name() . "/" . expand("%:t")

let &titlestring = hostname() . " -- vim " . Filename()
if &term[:5] == "screen"
  set t_ts=^[k
  set t_fs=^[\
  set title
autocmd TabEnter,WinEnter,BufReadPost,FileReadPost,BufNewFile * silent execute '!printf "\033]0;'.hostname().' -- vim '.Filename().'\007"'
autocmd TabEnter,WinEnter,BufReadPost,FileReadPost,BufNewFile * let &titlestring = hostname() . ' -- vim ' . Filename()

Here Filename can be customized to get your own header flavor. autocmd makes sure things get reloaded when moving between buffers, windows and the like. gitbranch in my example is a plugin available for git generating (as you might expect) the branch name when editing files in repositories.

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.