Show only current directory name (not full path) on bash prompt

76

31

The way my bash prompt is currently configured, it shows the whole path to the current directory. This is annoying when I'm deep inside a directory tree, as the prompt becomes so long that every command wraps into the next line. How do I make it show only the last part of the path?

This is what I have in my .bashrc:

PS1='${debian_chroot:+($debian_chroot)}\[\033[01;32m\]\u@\h\[\033[00m\]:\[\033[01;34m\]\w\[\033[00m\]\$ '

# If this is an xterm set the title to user@host:dir
case "$TERM" in
xterm*|rxvt*)
    PROMPT_COMMAND='echo -ne "\033]0;${USER}@${HOSTNAME}: ${PWD/$HOME/~}\007"'
    ;;
*)
    ;;
esac

Helder S Ribeiro

Posted 2009-10-25T21:38:55.423

Reputation: 5 997

Answers

104

Change the \w (lowercase) to \W (uppercase):

PS1='${debian_chroot:+($debian_chroot)}\[\033[01;32m\]\u@\h\[\033[00m\]:\[\033[01;34m\]\W\[\033[00m\]\$ '
                                                                                       ^^
           this one waaaaaay over here ------------------------------------------------+    

Have a look at the Bash Prompt HOWTO for lots of fun details. example:

user@host:/usr/local/bin$ echo $PS1
${debian_chroot:+($debian_chroot)}\[\033[01;31m\]\u@\h\[\033[00m\]:\[\033[01;36m\]\w\[\033[00m\]\$ 

user@host:/usr/local/bin$ export PS1='${debian_chroot:+($debian_chroot)}\[\033[01;31m\]\u@\h\[\033[00m\]:\[\033[01;36m\]\W\[\033[00m\]\$ '

user@host:bin$

The PROMPT_COMMAND variable, if set, is a command that gets run before displaying the prompt specified in PS1. In your case, PROMPT_COMMAND runs an echo statement with certain ANSI escape sequences that manipulate the titlebar of an Xterm.

If you suspect your PROMPT_COMMAND is overriding your PS1 prompt, you can unset it and test things out:

$ unset PROMPT_COMMAND

Finally, be sure that you're changing the PS1 definition that actually gets used. Common locations are /etc/bash.bashrc, /etc/profile, ~/.bashrc, ~/.bash_profile, ~/.profile. The system files are generally (but not always) run before the user files.

quack quixote

Posted 2009-10-25T21:38:55.423

Reputation: 37 382

Great answer. Make sure you reboot in order this to take effect. Thanks! – Combine – 2018-05-31T09:00:57.723

Hm... I'm afraid it's already \w, but it seems like that case statement overrides it when i'm on an xterm, and the problem seems to be with the PWD in the PROMPT_COMMAND line. Do you know what I should put there? – Helder S Ribeiro – 2009-10-25T22:48:55.750

4\w (lower case) sets it to full path, \W (uppercase) trims to the final bit. the PROMPT_COMMAND is setting the window title in an xterm. check your TERM variable; if it doesn't start with "xterm" or "rxvt" then PROMPT_COMMAND isn't even getting run. – quack quixote – 2009-10-25T22:59:13.297

Oh, yeah, duh. Sorry, I mixed upper and lowercase. That worked. Thanks! :) – Helder S Ribeiro – 2009-10-25T23:39:24.323

15

Simple bash replace command is

${VAR/pattern_to_find/pattern_to_replace}

For showing the last directory you can just do ${PWD/*\//}, i.e. find any thing before and including the last '/' and replace it with nothing.

On my ubuntu machine I use:

export PS1='$(whoami):${PWD/*\//}#'. 

stopBugs

Posted 2009-10-25T21:38:55.423

Reputation: 151

1I like this answer better than the accepted one because it's generic to any situation instead of just the special parsing logic of $PS1. Fewer more powerful tools are easier to remember and compose. :) – David Ellis – 2018-06-07T17:03:26.353

4

My solution is to show the top three and bottom 2 directories when there are more than 5

So my prompt (which has other info too) looks like:

08:38:42 durrantm U2017 /home/durrantm/Dropbox/_/rails/everquote

when my pwd is actually

/home/durrantm/Dropbox/93_2016/work/code/ruby__rails/rails/everquote

My PS1 prompt is setup as follows:

HOST='\[\033[02;36m\]\h'; HOST=' '$HOST
TIME='\[\033[01;31m\]\t \[\033[01;32m\]'
LOCATION=' \[\033[01;34m\]`pwd | sed "s#\(/[^/]\{1,\}/[^/]\{1,\}/[^/]\{1,\}/\).*\(/[^/]\{1,\}/[^/]\{1,\}\)/\{0,1\}#\1_\2#g"`'
BRANCH=' \[\033[00;33m\]$(git_branch)\[\033[00m\]\n\$ '
PS1=$TIME$USER$HOST$LOCATION$BRANCH

git_branch is a function which shows current git branch, I keep it in my dotfiles, it is:

git_branch () {
  git branch 2> /dev/null | sed -e '/^[^*]/d' -e 's/* \(.*\)/\1/'
  }

Michael Durrant

Posted 2009-10-25T21:38:55.423

Reputation: 978

This is awesome! Thanks a lot for this answer. – Carlos F – 2019-09-29T23:27:03.170

4

My solution for this is slightly different in regards to how do I export it, so thought I'd share it here:

Create another prompt string variable; PS5 and export the following string in your .profile / .bash_profile file:

\u: Display the current username .

\W: Print the base of current working directory.

# Display username and current directory only.
export PS5='export PS1="\u:\W$";';

Now whenever you need to use the shorthand-ed PS, just run: eval $PS5


Or even better yet, create an alias in your .bash_aliases file: (thanks to @muru)

alias PS5='export PS1="\u:\W$";';

source again, and now you can just type PS5 to switch.

U-ways

Posted 2009-10-25T21:38:55.423

Reputation: 161

1This looks like a frankenalias. Why not just use an alias or a function? – muru – 2018-08-19T01:31:43.843

1

I believe this option is much easier, by simply doing:

echo $PWD | rev | cut -d '/' -f 1 | rev

So assign this to the PS1 variable in your .bashrc file:

PS1='$(PWD | rev | cut -d '/' -f 1 | rev)'

Dani Mach

Posted 2009-10-25T21:38:55.423

Reputation: 11

1

Show only current directory name (not full path) on bash prompt

Most of the other solutions did not work for me across all of my OSes that share my dot files: AIX, Windoze, and Linux. The bash ports were old versions that didn't support certain constructs and I didn't want to fork another process (i.e. sed, awk, etc.) which is noticeably expensive under cygwin.

The following is long but performant:

# takes a number argument of the number of last dirs to show
function DIR_LAST {
    # read -a didn't seem to work under bash 3
    IFS='/' array=($PWD)
    len=${#array[@]}
    start=$((len - $1))
    # leading / if fewer dir args: /usr/flastname not usr/flastname
    if (( $start <= 1 )); then
        start=1
        echo -n /
    fi
    for (( i = $start; $i < $len; i++ )); do
        if (( $i > $start )); then
            echo -n /
        fi
        echo -n ${array[$i]}
    done
}
export PS1="\$(DIR_LAST 2) {$(hostname)} "

I want it to spit out:

/
/usr
/usr/foo
foo/bin

Notice the lack of a leading slash in the last line which is how I like it. Also, you can spit out the last 3 directories by changing the arg to DIR_LAST.

Also, I tried to do this with a regex and BASH_REMATCH but bash v3 didn't seem to like the parens and I couldn't figure out how to properly escape them. Sigh.

Gray -- SO stop being evil

Posted 2009-10-25T21:38:55.423

Reputation: 269

0

root:~/project#  -> root:~/project(dev)# 

add the following code to the end of your ~/.bashrc

force_color_prompt=yes
color_prompt=yes
parse_git_branch() {
git branch 2> /dev/null | sed -e '/^[^*]/d' -e 's/* \(.*\)/(\1)/'
}
if [ "$color_prompt" = yes ]; then
PS1='${debian_chroot:+($debian_chroot)}\[\033[01;32m\]\u@\h\[\033[00m\]:\[\033[01;34m\]\w\[\033[01;31m\]$(parse_git_branch)\[\033[00m\]\$ '
else
PS1='${debian_chroot:+($debian_chroot)}\u@\h:\w$(parse_git_branch)\$ '
fi
unset color_prompt force_color_prompt

Ali Alp

Posted 2009-10-25T21:38:55.423

Reputation: 101