Bash – Compact Bash Prompt for Directory Tree and Filename

bashdirectorydirectory-structurepromptpwd

In a system with Ubuntu 14.04 and bash, I have the PS1 variable ending with the following contents:

\u@\h:\w\$

so that the prompt appears as

user@machinename:/home/mydirectory$

Sometimes, however, the current directory has a long name, or it is inside directories with long names, so that the prompt looks like

user@machinename:/home/mydirectory1/second_directory_with_a_too_long_name/my_actual_directory_with_another_long_name$

This will fill the line in the terminal and the cursor will go to another line, which is annoying.

I would like instead to obtain something like

user@machinename:/home/mydirectory1/...another_long_name$

Is there a way to define the PS1 variable to "wrap" and "compact" the directory name, to never exceed a certain number of characters, obtaining a shorter prompt?

Best Answer

First of all, you might simply want to change the \w with \W. That way, only the name of the current directory is printed and not its entire path:

terdon@oregano:/home/mydirectory1/second_directory_with_a_too_long_name/my_actual_directory_with_another_long_name $ PS1="\u@\h:\W \$ "
terdon@oregano:my_actual_directory_with_another_long_name $ 

That might still not be enough if the directory name itself is too long. In that case, you can use the PROMPT_COMMAND variable for this. This is a special bash variable whose value is executed as a command before each prompt is shown. So, if you set that to a function that sets your desired prompt based upon the length of your current directory's path, you can get the effect you're after. For example, add these lines to your ~/.bashrc:

get_PS1(){
        limit=${1:-20}
        if [[ "${#PWD}" -gt "$limit" ]]; then
                ## Take the first 5 characters of the path
                left="${PWD:0:5}"
                ## ${#PWD} is the length of $PWD. Get the last $limit
                ##  characters of $PWD.
                right="${PWD:$((${#PWD}-$limit)):${#PWD}}"
                PS1="\[\033[01;33m\]\u@\h\[\033[01;34m\] ${left}...${right} \$\[\033[00m\] "
        else
                PS1="\[\033[01;33m\]\u@\h\[\033[01;34m\] \w \$\[\033[00m\] "
        fi


}
PROMPT_COMMAND=get_PS1

The effect looks like this:

terdon@oregano ~ $ cd /home/mydirectory1/second_directory_with_a_too_long_name/my_actual_directory_with_another_long_name
terdon@oregano /home...th_another_long_name $ 
Related Question