I am customizing my PS1 prompt, specifically the $PWD part which is delimited by /'s

among several things I like having the current directory.
However if the directory is too long I'd like to have beginning...ending

For example, instead of

otherstuff:~/apps/webs/2014/area1/groupa/current:other_stuff $ 

I'd like to have the first directories and the last two, i.e.

otherstuff:~/apps/webs/.../groups/current:other_stuff $ 

It should handle when they partially overlap, i.e.

   otherstuff:~/apps/webs/2014:other_stuff $ 
-> otherstuff:~/apps/webs/2014:other_stuff $ 

and when they are the same, i.e.

   otherstuff:~/apps/webs/:other_stuff $ 
-> otherstuff:~/apps/webs/:other_stuff $ 

I tried various substrings if $PWD using {}, () and {} but can't get the format right.

Update - I used the information in guidos answer (accepted) to put together this:

parse_git_branch () {
  git branch 2> /dev/null | sed -e '/^[^*]/d' -e 's/* \(.*\)/\1/'
PS1=$PS1'`pwd | sed "s#\(/[^/]\+/[^/]\+/\).*\(/[^/]\+/[^/]\+\)/\?#\1...\2#g"`'
PS1=$PS1'\033[00m\]:\033[01;33m\]$(parse_git_branch)\[\033[00m\]\n\$ '

which yields:

enter image description here

A sad amount of the code is repeated \033[00m\]:'s for the 3 white colon seperator !


This sed command runs a regex that should be helpful for your task:

 sed 's#\(/[^/]\+/[^/]\+/\).*\(/[^/]\+/[^/]\+\)/\?#\1...\2#g'


$ echo "~/apps/webs/2014/" | sed $PS1PWD_REGEX 
$ echo "~/apps/webs/chip/mips/2014/" | sed $PS1PWD_REGEX 
$ echo "~/apps/webs/chip/mips/2014" | sed $PS1PWD_REGEX 
$ echo "/apps/webs/chip/mips/clips/2014" | sed $PS1PWD_REGEX 
$ echo "/" | sed $PS1PWD_REGEX 
$ echo "~" | sed $PS1PWD_REGEX

You might then setup your profile in the lines:

export PS1='[\u@\h `pwd | sed "s#\(/[^/]\+/[^/]\+/\).*\(/[^/]\+/[^/]\+\)/\?#\1...\2#g"`]\$ '

I myself prefer a multiline prompt which gives plenty of space for long paths on the first line.

  • +1 yeah I go with the carriage return at the end but I am displaying so much other stuff in my PS1 now that even the full dir path is too long! Thanks for this great answer. likely to accept it. upvoted as a minimum. – Michael Durrant Apr 12 '14 at 14:26
  • 1
    you welcome; did you try something from here? some awesome stuff (maybe even too much for my eyes): askapache.com/linux/bash-power-prompt.html – guido Apr 12 '14 at 14:32
  • yup, see my updated answer! Includes git branch! – Michael Durrant Apr 12 '14 at 15:02

You should just split it and choose the parts you want:

( IFS=/ ; set -- $string 
  while ${1+:} false ; do 
    echo "$1" ; shift

To get only the beginning/end:

start_end="$(IFS=/ ; set -- $string ; unset IFS
    printf '/%s/.../%s' "$1" \
        "`shift $(($#-1)) ; echo "$1"`"

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.