Is Your Bash Prompt Cramping Your Style?
It is sometimes hard to form a mental model of a directory tree when working with the command line. GUI shells tend to provide more visual cues. For example, in OS X, the Finder has a column view that allows you to quickly see how directories are nested.

So, like a lot of Bash users, I used to get around this by printing the current working directory in my shell prompt:

However, things can get pretty cramped when dealing with deeply nested directories. A better solution is needed. Ideally, I want a minimal prompt that just displays my user@host. I only need to get my bearings when I’m moving around in the directory tree. Therefore, I’ve come up with the following.

The current working directory is printed after every cd. This allows me to get my bearings when I need to, while keeping my Bash prompt short and sweet. The following incantation in ~/.bashrc does the trick:
# Print working directory after a cd.
cd() {
if [[ $@ == '-' ]]; then
builtin cd "$@" > /dev/null # We'll handle pwd.
else
builtin cd "$@"
fi
echo -e " \033[1;30m"`pwd`"\033[0m"
}
Have you come up with other solutions for longpromptitis? Let me know in the comments!
Woooah, slow down. You post far to often.
;)
In ZSH, there’s an environment variable called $RPS1 which gives the right aligned prompt text. My specific settings are:
PS1=’%B(%h) %m%#%b ‘
RPS1=’(%20<…<%~)'
and here is how they appear.
http://imgur.com/OAZhC
@Clinton: I must say that ZSH handles this much better than Bash does.
I simply set PS1=”[\t][\u@\H:\w]\r\n$ ” which gives me a prompt looking like
[16:02:33][chrisw@arch:/mnt/Storage/workspace]
$
Can I ask what terminal program you’re running, and how you got it to appear like that? Specifically, the info bar at the bottom and the color scheme.
Kevin, I’m using Terminal.app with a SIMBL plugin called terminalcolours to customise the colours. The theme is a modified version of ir_black.
The bar at the bottom is a tmux status bar.
Awesome, thanks for the info and the links!
I use a very simple prompt. Just the hostname up to the first dot, and the last part of the path (up to the last slash).
PS1=’[\h] \W> ‘
It looks like: [compute-0-29] log>
[compute-0-29] log> hostname
compute-0-29.local
[compute-0-29] log> pwd
/var/log
I use this because I usually don’t really need to know all the hostname nor the full path.
Agreed. I like having the following displayed:
1. Username (to make sure I’m in the correct context)
2. Complete, current work directory path
3. Hostname (to make sure I’m issuing on the right host in this terminal)
4. Most importantly… a consistent cursor position for command entry
export PS1=”[\u:\w]\n\h:”
This looks like…
[theUserName:/data/subdir/subdir2/subdir3]
hostname:
The cursor is placed after the colon. Independent of the working directory depth, the command is issued at the same location.
Add this command to your .bashrc:
proml () { case $TERM in xterm*) PS1="\\[\33]0;\\u@\\h \\w\0733[7m\\]: \\u@\\h {\${HISTCMD}} \$;\\[33[m\\] " ;; *) PS1="\\[33[7m\\]: \\u@\\h {\\!} \$;\\[33[m\\] " ;; esac; export PS1 }And your prompt will look like this:
: scs@phred {321} $;but the banner at the top of your terminal window will be painted with the path (among other things). Most of the explanation of those things will be left to the student, but one of the non-obvious features is that a prompt like that can be cut and pasted along with any trailing command, and only the trailing command will be executed. The prompt will be ignored when pasted.
I recommend the Bash Prompt Howto page at http://tldp.org/HOWTO/Bash-Prompt-HOWTO/, especially section 6.3 on how to set the banner bars.
I use a two lines prompt and I also update the title of the xterm window after each command.
The prompt looks like that
where @ is a blank character with a colored background. In the example below, that color is controlled by the col2 escape sequence which uses the 256 color extension of XTerm for a more pleasing look. Most modern terminal emulators support 256 colors but the linux console (TERM=console) does not.
Also, I recompute the prompt after each command using PROMPT_COMMAND. This is not stricly required but that potentially allows more complex customizations
================
export PROMPT_COMMAND='set-xterm-title ; set-prompt' XTERM_TITLE="Term" function set-xterm-title () { local title title=$PWD title=${title//#$HOME/\~}/ if [ -n "$XTERM_TITLE" ] ; then title="$XTERM_TITLE [$title]" fi echo -ne "33]0;$title07" } function set-prompt () { local col0="\[\e[0m\]" # reset local col1="\[\e[1;31m\]" # pwd color local col2="\[\e[48;5;$((16+36*2+6*2+6))m\]" # left margin color local col3="\[\e[1;33m\]" # [user@host] color PS1="\n$col2 $col0 $col3[\u@\h] $col1\w$col0 \n$col2 $col0 " }@Steve Simmons: That’s a neat idea, having a prompt that is ignored when the whole line is copied and pasted.
Hoops! The formating messed up my commands. It is unfortunately not possible to test before posting but I hope this works better:
export PROMPT_COMMAND="set-xterm-title ; set-prompt" XTERM_TITLE="Term" function set-xterm-title () { local title title=$PWD title=${title//#$HOME/\~}/ if [ -n "$XTERM_TITLE" ] ; then title="$XTERM_TITLE [$title]" fi echo -ne "33]0;$title07" } function set-prompt () { local col0="\[\e[0m\]" # reset local col1="\[\e[1;31m\]" # pwd color local col2="\[\e[48;5;$((16+36*2+6*2+6))m\]" # left margin color local col3="\[\e[1;33m\]" # [user@host] color PS1="\n$col2 $col0 $col3[\u@\h] $col1\w$col0 \n$col2 $col0 " }Actually I’d think that the moment I use ‘cd’ is also the moment I least need to know $(pwd). I have that information in PS1 so that when I come back to a shell I immediately know where I am. If I use ‘cd’ I already know where I’m going.
I feel the same as Gwh. Personally I use a truncated pwd so that when it gets too long only the end of it is shown. As a matter of fact, for this purpose I’ve created a shell scirpt () which shows only the end of the pwd. I use it as „PS1=’$(tpwd -n 30 {)\$ ‘”. This is similar to the way ZSH’s “%20<…<%~” works shown by Clinton Curry.
Also, I've never felt the need for my prompt be ignored where pasting like Steve Simmons' is even though my PS2 is „:; ”. ;) Still, even this I rarely care about.
In my opinion, there are far better ways to improve the prompt. For instance, as a programmer I find it invaluable that my prompt prints the name of a checked out git branch if I happen to be in a git repository. It also changes username's colour if I'm root, hostname's colour when I'm connected via SSH, and the trailing „$” when the previous command finished unsuccessfully. Those visual indicators proven to be rather handy. My whole prompt can be found at .
Any way, the prompt is a matter of taste, so everyone who uses shell all the time should spend some time customising it.
I use this trick: http://www.tldp.org/HOWTO/Bash-Prompt-HOWTO/x783.html
I recently blogged about the customizations I made to my ZSH prompt. I split the prompt in 2 lines.
http://blog.dannynavarro.net/2010/10/16/zsh-prompt-for-virtualenv-git-and-bzr/
In the post I don’t show that in the case the path line gets too long, the path gets truncated from the left side. That’s usually is enough to give enough context.
I’ve gone for a simpler hostname + innermost two directories; that seems to be enough to remember where I am. In tcsh:
set prompt = ‘%m %B%C2%b > ‘
(%m is hostname, %B and %b turn on and off bold, and %Cn is the n innermost levels of the path. )
I do like the two-line idea, though I also value compactness (it makes a small embedded terminal in e.g. kate more useful)… hm. I’ll have to test it at some point.
Here are some ideas what to do with your prompt
http://matt.might.net/articles/console-hacks-exploiting-frequency/
I use PROMPT_COMMAND so that after each directory change it displays new directory only once together with last seven modified filename like this:
lost> cd /
/: tmp etc root dev sbin bin lib
lost> cd /tmp
/tmp: vnc.err orbit-cougar plugtmp-159 FlashXXhNLOze cvs3cz4lF~ plugtmp-158 svi69.tmp
lost> cd
/home/cougar: Mail Download dead.letter zx1 zx2 test calendar.vcf
I wrote a script (I call it ‘sd’ for Stored Directory”) which let’s me assign number, letters, or strings to directories. by typing sd 1 `pwd` it stores the current directory at “1″, and to cd to this dir all I have to type from now on is ‘sd 1′
I like this a whole lot better than that push/pop dir thing people always talk about. and also sd stored the directories in a temp file in your home directory, so it works across multiple shells and after reboots and such.
#!/bin/bash sdfile="$HOME/.stored-paths" function delete_entry { newfile="" firstline=1; while read line; do i=`echo $line | cut -d\ -f1` if [[ "$i" != "$1" ]] ; then if [[ "$firstline" == "0" ]] ; then newfile="$newfile"$'\n' else firstline=0 fi newfile="$newfile""$line" fi done $sdfile # eval echo "\${newfile%\$'\n'}" #> #sdfile } function store_entry { while read line; do i=`echo $line | cut -d\ -f1` if [[ "$i" == "$1" ]] ; then delete_entry "$i" break fi done > $sdfile sort < $sdfile -o $sdfile } function change_dir { while read line; do i=`echo $line | cut -d\ -f1` if [[ "$1" == "$i" ]] ; then dir="`echo $line | cut -f 2 -d\ `" cd "$dir" echo "$dir" return 0 fi done &2 return 1 } if [[ -f $sdfile ]]; then echo > /dev/null else touch $sdfile fi if [[ "$1" == "--clear" ]] ; then printf "" > $sdfile elif (( $# == 0 )) ; then cat "$sdfile" elif [[ "$1" == "-d" ]] ; then delete_entry "$2" elif [[ "$2" != "" ]] ; then store_entry "$1" "$2" elif [[ "$1" != "" ]] ; then change_dir "$1" return "$?" elif "$1" == "-h" || "$1" == "--help" ; then echo "sd - store directories for quick cd'ing" echo "Copyright (C) Brandon Captain. Released under the GPL v2." echo "" echo "Usage: sd 1 /usr/src/linux/ # store path at identifier '1'" echo "Usage: sd bin /usr/bin # store path at identifier 'bin'" echo "Usage: sd 1 # cd to path at identifier '1'" echo "Usage: sd # show all paths" echo "Usage: sd -d 1 # clear path 1" echo "Usage: sd --clear # clear all paths" echo "Usage: sd -h # this help screen" echo "Usage: sd --help # this help screen" fiWould you be willing to post that snazzy tmux config?
Thanks for the great post!
@invaderzim: Sure, here’s my .tmux.conf:
The only thing I do differently is add an “ls” in there. I see the directory contents every time I change directories.
[...] however it wasn’t complete for people in the default Ubuntu Linux environment. The article, here, shows that by adding this amount of code to your ~/.bashrc file you can modify your prompt: # [...]
Am I the only one missing bash’s TAB completion after sourcing your cd() function?
Bacus, tab completion still works for me.