22

My Bash Prompt is currently setting the xterm titlebar using the following sequence:

PS1='\033]0;\u@\h>\w\007'

Is there an easy way to display the current command in the titlebar. For example, if I am tailing a file using tail -f foo.log, I want my titlebar to say tail -f foo.log.

14

Basically, you need:

trap 'printf "\033]0;%s\007" "${BASH_COMMAND//[^[:print:]]/}"' DEBUG

at the end of your .bashrc or similar. Took me a while to work this out -- see my answer here for more information :)

  • Thanks for this solution simon! However, when adding this to my .bashrc after each command in my shell I get this output 0;%s@%s:%s" "${USER}" "${HOSTNAME%%.*}" "${PWD/#$HOME/~}. I assume that I can suppress this output by assigning the trap command to PS1? However, PS1=trap 'echo -ne "\033]0;$BASH_COMMAND\007"' DEBUG does not work. It leads to the error bash: echo -ne "\033]0;$BASH_COMMAND\007": command not found. – orschiro Dec 7 '13 at 8:17
  • BTW, I just fielded stackoverflow.com/questions/48407130/…, asked presumably as a result of this advice being applied. The trap should be writing to stderr or to the TTY directly, not to stdout. – Charles Duffy Jan 23 '18 at 17:28
  • 1
    @orschiro, the advice to run the trap command as a separate command, not to assign it to PS1. – Charles Duffy Jan 23 '18 at 17:29
13

(Inspired by this SU answer)

You can combine a couple bash tricks:

  • If you trap a DEBUG signal, the handler is called before each command is executed
  • The variable $BASH_COMMAND holds the currently executing command

So, trap DEBUG and have the handler set the title to $BASH_COMMAND:

trap 'printf "\033]0;%s\007" "${BASH_COMMAND//[^[:print:]]/}" >&2' DEBUG

This will keep the title changed until something else changes it, but as long as your $PS1 stays the same it won't be a problem -- you start a command, the DEBUG handler changes the titlebar, and when the command finishes bash draws a new prompt and resets your titlebar again.

A useful tip found here (also where that SU answer came from) is to include:

set -o functrace

This will make bash propagate the DEBUG trap to any subshells you start; otherwise the titlebar won't be changed in them

  • ha! same answer at exactly the same time! +1 for handling subshells, but do you have any answer to the pipes problem? (see my link to the SO question) – simon Mar 10 '11 at 15:47
  • Doesn't work through ssh – abyss.7 Feb 15 '16 at 8:16
  • Also "kills" the completion on "tab" – abyss.7 Feb 15 '16 at 8:32
  • BTW, I just fielded stackoverflow.com/questions/48407130/…, asked presumably as a result of this advice being applied. The trap should be writing to stderr or to the TTY directly, not to stdout. – Charles Duffy Jan 23 '18 at 17:29
  • Wouldn't it be better to redirect to /dev/tty instead of stderr? – Aaron Digulla Mar 26 at 9:26
2

I worked around my own solution from various posts around. This creates a title containing user, hostname, pwd, tty and currently executed command (for bash).

This looks like this (no command being executed):

.:[user@hostname:/home/user][pts/10]:.

And like this (executing a command):

.:[user@hostname:/home/user][pts/10] {tail -F /var/log/syslog}:.

Somewhere in the .bashrc, i extended PS1:

# set the terminals title. This is the "post-command" part,
# need to use a trap for pre-command (to add the command line to the title)
PS1+="\[\033]2;.:[\u@\h:\$PWD] [$(tty | cut -b 6-)]:.\007\]"

Adds the current command, using history 1 and trap:

# set a fancy title (this is pre-command, in PS1 is after-command (to reset command)
trap 'echo -ne "\033]2;.:[${USER}@${HOSTNAME}:${PWD}] [$(tty | cut -b 6-)] {$(history 1 | sed "s/^[ ]*[0-9]*[ ]*//g")}:.\007"' DEBUG

Feel free to adopt to your needs.

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.