I implemented a prompt path shortener for bash to be included in the PS1 environment variable, which shortens the working directory into something more compact but still descrip
This was my own solution when I had the idea for this challenge. The inspiration actually came from Jolexa's Blog.
So here it is, the ruby implementation in readable form:
a = ARGV[1].gsub(%r{^#{ENV['HOME']}}, "~")
b, a = a, a.gsub(%r{/(\.?[^/.])[^/]+(/.*)}, '/\1\2') while
(a.length > ARGV[2].to_i) && (b != a)
print a
And the actual one-line implementation within the bash function:
_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'
}
Pure Bash:
_dir_chomp () {
local IFS=/ c=1 n d
local p=(${1/#$HOME/\~}) r=${p[*]}
local s=${#r}
while ((s>$2&&c<${#p[*]}-1))
do
d=${p[c]}
n=1;[[ $d = .* ]]&&n=2
((s-=${#d}-n))
p[c++]=${d:0:n}
done
echo "${p[*]}"
}
For purposes of testing, I'm assuming that the question means that the current user is "user1".
Note: Bash 4 has a variable PROMPT_DIRTRIM
that shortens the \w
escape in PS1
by retaining the number of sub-directories according to its value and replacing the rest with ...
/$ PROMPT_DIRTRIM=2
/$ echo $PS1
\w\$
/$ pwd
/
/$ cd /usr/share/doc/bash
.../doc/bash$
This one is 20 or so characters shorter than my other answer:
_dir_chomp () {
local p=${1/#$HOME/\~} b s
s=${#p}
while [[ $p != "${p//\/}" ]]&&(($s>$2))
do
p=${p#/}
[[ $p =~ \.?. ]]
b=$b/${BASH_REMATCH[0]}
p=${p#*/}
((s=${#b}+${#p}))
done
echo ${b/\/~/\~}${b+/}$p
}
This is how I shorten my bash prompt w/ full path in titlebar (works since 3.0):
_PS1P=('' '..')
PROMPT_COMMAND='_PS1L=${#DIRSTACK[0]} _PS1D=${DIRSTACK[0]}'
PS1='\[\e]2;\h:\w\a\]\h ${_PS1P[$_PS1L>36]}${_PS1D:$_PS1L>36?-34:0} \$ '
This method requires very low CPU overhead.
Another solution with only bash internals, no use of sed
shortpath()
{
dir=${1%/*} && last=${1##*/}
res=$(for i in ${dir//\// } ; do echo -n "${i:0:3}../" ; done)
echo "/$res$last"
}
My previous solution, with bash and sed. it cut each dir in 3 first caracters and add '..' like this: /hom../obo../tmp../exa../bas../
shortpath()
{
dir=$(dirname $1)
last=$(basename $1)
v=${dir//\// } # replace / by <space> in path
t=$(printf "echo %s | sed -e 's/^\(...\).*$/\\\1../' ; " $v)
# prepare command line, cut names to 3 char and add '..'
a=$(eval $t)
# a will contain list of 3 char words ended with '..' ans separated with ' '
echo " "$a"/"$last | sed -e 's/ /\//g'
}