I am using Ubuntu and I am tired of this long prompts in bash when I am working with some deep directory hierarchy. So, I would like to tweak my PS1 to shorten the working d
Not so different from previous solutions. However, maybe a bit more readable/editable. However, no solution to the folder name boundary, only focusing on the length of the prompt.
### SET MY PROMPT ###
if [ -n "$PS1" ]; then
# A temporary variable to contain our prompt command
NEW_PROMPT_COMMAND='
pwd_short=${PWD/#$HOME/\~};
if [ ${#pwd_short} -gt 53 ]; then
TRIMMED_PWD=${pwd_short: 0: 25}...${pwd_short: -25}
else
TRIMMED_PWD=${pwd_short}
fi
'
# If there's an existing prompt command, let's not
# clobber it
if [ -n "$PROMPT_COMMAND" ]; then
PROMPT_COMMAND="$PROMPT_COMMAND;$NEW_PROMPT_COMMAND"
else
PROMPT_COMMAND="$NEW_PROMPT_COMMAND"
fi
# We're done with our temporary variable
unset NEW_PROMPT_COMMAND
# Set PS1 with our new variable
# \h - hostname, \u - username
PS1='\u@\h: $TRIMMED_PWD\$ '
fi
added to the .bashrc file. All parts of the prompt is updated properly. The first part is shortened if you're in your home directory. Example:
user@computer: ~/misc/projs/solardrivers...src/com/mycompany/handles$
For people looking for a much simpler solution and don't need the name of the first directory in the path, Bash has built-in support for this using the PROMPT_DIRTRIM
variable. From the documentation:
PROMPT_DIRTRIM
If set to a number greater than zero, the value is used as the number of trailing directory components to retain when expanding the \w and \W prompt string escapes (see Printing a Prompt). Characters removed are replaced with an ellipsis.
For example:
~$ mkdir -p a/b/c/d/e/f
~$ cd a/b/c/d/e/f
~/a/b/c/d/e/f$ export PROMPT_DIRTRIM=2
~/.../e/f$ PROMPT_DIRTRIM=3
~/.../d/e/f$
Downside: It depends on the directory level, not the length of the path, which you might not want.
Upside: It's very simple. Just add export PROMPT_DIRTRIM=2
to your .bashrc
.
Apart from the bash-builtin solution using PROMPT_DIRTRIM
, you may want to try $(pwd | tail -c16)
, which is a tad simpler than most other answers, but just gives the last 16 characters of the current directory. Of course replace 16 by any number you want.
echo -n $PWD | sed -re "s|(~?/[^/]*/).*(.{$pwd_length})|\1...\2|"
sed with -r only for convenience, allows to omit backslash before parentheses, and "|" as delimiter only for convenience too - because we want to use the slash inside the command. I guess your home get's displayed as ~ as well, so ~/foo/bar/baz/ should end in ~/foo/.../baz, and /foo/bar/baz/ as /foo/.../baz/.
So we take an optional ~, followed by slash, name, slash as \1, then something, then the rest as \2.
Why not just use ${string:position:length}
?
You can do ${string:-$max_chars}
to have the last ${max_chars}
of the string.
note the negative value
Another approach, still using sed
and awk
to generate the prompt. This will convert your $HOME
directory into ~, show you your root directory, your lowest level (current directory), and its parent, separated by ..
for each directory in between.
Inside of your .bashrc
(or .bash_profile
on OS X):
function generate_pwd {
pwd | sed s.$HOME.~.g | awk -F"/" '
BEGIN { ORS="/" }
END {
for (i=1; i<= NF; i++) {
if ((i == 1 && $1 != "") || i == NF-1 || i == NF) {
print $i
}
else if (i == 1 && $1 == "") {
print "/"$2
i++
}
else {
print ".."
}
}
}'
}
export PS1="\$(generate_pwd) -> "
The script uses awk's built in NF
variable (number of fields) and positional variables ($1, $2 ...
) to print each field (directory name) separated by the ORS
variable (output record separator). It collapses the inner directories into ..
in your prompt.
Example of it in use:
~/ -> cd Documents/
~/Documents/ -> cd scripts/
~/Documents/scripts/ -> cd test1/
~/../scripts/test1/ -> cd test2
~/../../test1/test2/ -> pwd
/Users/Brandon/Documents/scripts/test1/test2
~/../../test1/test2/ -> cd test3/
~/../../../test2/test3/ -> cd test4/
~/../../../../test3/test4/ -> pwd
/Users/Brandon/Documents/scripts/test1/test2/test3/test4
~/../../../../test3/test4/ -> cd /usr/
/usr/ -> cd local/
/usr/local/ -> cd etc/
/usr/local/etc/ -> cd openssl/
/usr/../etc/openssl/ -> cd private/
/usr/../../openssl/private/ ->