Linux: My bash prompt

There seems to be a semi-meme going around on some of the planets I read.

My concern is long directory paths and I wanted a dymanic solution for it. Surely, I cannot be the first person to think of it, but I haven’t seen it in use anywhere else.

jolexa @ helios :: ~ %%
and
jolexa @ helios :: ~ %% cd projects/prefix-tinderbox/really_long_dirname_so_that_binpkgs_can_be_shortened/a/b/ jolexa @ helios :: .../a/b %%

(the colors and wrapping are representitive only)

and the code that produces that:

_chomp_path() {
    local path=${1/${HOME}/\~}
    local last=${path} sedout= count=0 count2=0
    sedout=$(echo ${path} | sed -e 's:/: :g')
    for i in ${sedout}; do
        (( count++ ))
    done
    if ((count > 2)); then
        last="..."
        for i in ${sedout}; do
        (( count2++ ))
        if (( count2 >=  count - 1 )); then
            last+="/$i"
        fi
        done
    fi
    echo ${last}
}

PS1='\[\033[1;34m\]\u \[\033[1;32m\]@\[\033[1;34m\] \h \[\033[1;30m\]::\[\033[1;37m\] $(_chomp_path $(pwd)) \[\033[1;30m\]%%\[\033[0m\] '

If anyone wants to improve that function, let me know. It “fails” on directories with spaces in it.

16 Comments

  • August 16, 2010 - 2:41 pm | Permalink

    Nice idea ;)

    I still prefer my two line solution though, that way I always know where to look for my prompt :p

  • August 16, 2010 - 3:25 pm | Permalink

    A nice one. I want to keep my prompt short so now it shows only last directory in path. Sometimes one dir is too little so when I’ll have some time I’ll try showing two like you do :)

  • Florian (SuperFlo) CROUZAT
    August 16, 2010 - 3:47 pm | Permalink

    As I told you on IRC, bash4 as a builtin setting for that: PROMPT_DIRTRIM.

    • August 16, 2010 - 3:54 pm | Permalink

      Yea, that makes life alot simpler. So,


      PROMPT_DIRTRIM=2
      PS1='\[\033[1;34m\]\u \[\033[1;32m\]@\[\033[1;34m\] \h \[\033[1;30m\]::\[\033[1;37m\] \w \[\033[1;30m\]%%\[\033[0m\] '

      will deprecate my _chomp_path() function. I’ll check for bash version and keep the function for bash-3 boxes but that will become useless over time too. Anyway, thx!

  • August 16, 2010 - 4:29 pm | Permalink

    How about an ruby path shortener?

    ruby -e’a=”‘$(pwd)’”;b,a=a,a.gsub(%r{/([^/])[^/]+(/.*)},”/\\1\\2″)while(a.length>20)&&(b!=a);puts a’

    • August 16, 2010 - 4:30 pm | Permalink

      Arrgh, the comment engine destroyed my quote signs… Just replace accordingly. Or does this work?

      ruby -e'a="'$(pwd)'";b,a=a,a.gsub(%r{/([^/])[^/]+(/.*)},"/\\1\\2")while(a.length>20)&&(b!=a);puts a'

    • August 16, 2010 - 4:36 pm | Permalink

      And more improved:

      ruby -e'a="'$(pwd)'".gsub(%r{^'$HOME'},"~");b,a=a,a.gsub(%r{/([^/])[^/]+(/.*)},"/\\1\\2")while(a.length>15)&&(b!=a);puts a'

      I think I’ll go with that. :-)

    • August 16, 2010 - 4:48 pm | Permalink

      Boils down to having:


      _dir_chomp() {
      ruby -e'a="'$1'".gsub(%r{^'$HOME'},"~");b,a=a,a.gsub(%r{/(\.?[^/.])[^/]+(/.*)},"/\\1\\2")while(a.length>'$2')&&(b!=a);print a'
      }

      From prompt (PS1) call with:


      $(_dir_chomp "$(pwd)" 20)

      for a max length of 20.

  • gregf
    August 16, 2010 - 5:50 pm | Permalink

    Not sure if bash has something similar or not, but in zsh you can do PS1=”%2c” and it would print the last two directories. Just change the number to display the amount of trailing directories you want printed.

  • Cynyr
    August 16, 2010 - 7:01 pm | Permalink

    Heres a bash 3 friendly (i think) space friendly version

    _chomp_path() {
    local path=${1/${HOME}/\~}
    local last=${path} sedout= count=0 path2=

    #bash is dumb, "${#path//[^'/']/}" fails.
    sedout="${path//[^'/']/}"
    count=${#sedout}
    if ((count > 2)); then
    last="..."
    path2=${path%/*}
    path2=${path2%/*}
    last+=${path//${path2}}
    fi
    echo ${last}
    }

  • August 16, 2010 - 9:37 pm | Permalink

    Fish has a similar prompt. it shows only the first letter of every directory but the last one, which is displayed entirely.

  • mv
    August 17, 2010 - 1:37 pm | Permalink

    The zsh prompt knows %<string< and similar commands to trim strings within the prompt and print dots for the omitted parts (BTW: zsh is much more convenient for interactive shell: All such interactive functions like prompts, completion, … are much more powerful – once properly configured).

    Another possibility is to use plain sh substitution which will make it work in a few lines.
    You might want to have a look at my bash and zsh prompt buried in the German forums which uses path shortening with changing colors for the omitted part (which is not directly possible with zsh) by means of sh substitution:
    http://forums.gentoo.org/viewtopic-p-4223650.html#4223650
    (to use it with zsh you must source the code using the lines at the end of the posting and set the option prompt_subst). The path cutting sequence is added into the PS1 code near the end of the function (after "if ${CUT}").

  • quincunx74
    August 19, 2010 - 7:00 am | Permalink

    The following awk code will work for arbitrary directory names. The number of directories to show has been parametrized.

    _chomp_path() {

    local path=${1/${HOME}/\~}

    awk -v path=”$path” -v limit=2 ‘BEGIN {
    dirparts = split(path,split_path,”/”)
    if ( dirparts-1 > limit ) {
    printf(“%s”,”…”)
    for (i=dirparts-limit+1;i<=dirparts;i++) {
    printf("/%s",split_path[i])
    }
    }
    else {
    printf("%",path)
    }
    }' /dev/null
    }

  • Florian
    September 6, 2010 - 7:28 am | Permalink

    Mhm, whenever I’m trying to use pwd instead of \w in my PS1 it’s never changing after a cd command.
    Also with a plain $(pwd) instead of $(_chomp_path $(pwd)).
    Any ideas?

    • September 23, 2010 - 10:15 am | Permalink

      Of course it won’t, it needs to be expanded, see PROMPT_COMMAND section in man bash.
      Tips : grep -i prompt_command ~/.bashrc should show: PROMPT_COMMAND=do_my_ps1 # where do_my_ps1 is a function of your own that can use pwd et al.

  • Leave a Reply

    Your email address will not be published. Required fields are marked *

    *

    You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>