我正在寻找一个Bash函数,可以缩短较长的路径名,以避免我的PS1变量过长。类似这样的函数:
/this/is/the/path/to/a/really/long/directory/i/would/like/shortened
可能会最终变成:
/t../i../t../p../to/a/r../l../d../i/w../like/shortened
我希望在我的 .bashrc 文件中使用一个能够接受路径和最大可接受字符数的缩短方法。
虽然结果不完全相同,但是我的~/.bashrc
包含以下内容
_PS1 ()
{
local PRE= NAME="$1" LENGTH="$2";
[[ "$NAME" != "${NAME#$HOME/}" || -z "${NAME#$HOME}" ]] &&
PRE+='~' NAME="${NAME#$HOME}" LENGTH=$[LENGTH-1];
((${#NAME}>$LENGTH)) && NAME="/...${NAME:$[${#NAME}-LENGTH+4]}";
echo "$PRE$NAME"
}
PS1='\u@\h:$(_PS1 "$PWD" 20)\$ '
该路径最多显示20个字符。如果路径超过20个字符,它将显示为/...d/like/shortened
或~/.../like/shortened
。
这里有一个仅使用bash的解决方案,您可能会喜欢。它将路径的每个部分缩短到最短的前缀,以便仍然可以通过tab键自动补全,并使用*代替..作为填充。
#!/bin/bash
begin="" # The unshortened beginning of the path.
shortbegin="" # The shortened beginning of the path.
current="" # The section of the path we're currently working on.
end="${2:-$(pwd)}/" # The unmodified rest of the path.
end="${end#/}" # Strip the first /
shortenedpath="$end" # The whole path, to check the length.
maxlength="${1:-0}"
shopt -q nullglob && NGV="-s" || NGV="-u" # Store the value for later.
shopt -s nullglob # Without this, anything that doesn't exist in the filesystem turns into */*/*/...
while [[ "$end" ]] && (( ${#shortenedpath} > maxlength ))
do
current="${end%%/*}" # everything before the first /
end="${end#*/}" # everything after the first /
shortcur="$current"
shortcurstar="$current" # No star if we don't shorten it.
for ((i=${#current}-2; i>=0; i--))
do
subcurrent="${current:0:i}"
matching=("$begin/$subcurrent"*) # Array of all files that start with $subcurrent.
(( ${#matching[*]} != 1 )) && break # Stop shortening if more than one file matches.
shortcur="$subcurrent"
shortcurstar="$subcurrent*"
done
begin="$begin/$current"
shortbegin="$shortbegin/$shortcurstar"
shortenedpath="$shortbegin/$end"
done
shortenedpath="${shortenedpath%/}" # strip trailing /
shortenedpath="${shortenedpath#/}" # strip leading /
echo "/$shortenedpath" # Make sure it starts with /
shopt "$NGV" nullglob # Reset nullglob in case this is being used as a function.
提醒一下,Bash 4+内置了一个\w
“缩短器”:
PROMPT_DIRTRIM=3
将/var/lib/whatever/foo/bar/baz
缩短为.../foo/bar/baz
。
sudo -s; echo /usr/local/bin/bash >> /etc/shells; chsh -s /usr/local/bin/bash
- neurotronix我对Evan Krall的代码进行了一些改进。现在它会检查你的路径是否以$HOME开头,并且用~/代替/h*/u*,使路径更加简短。
#!/bin/bash
begin="" # The unshortened beginning of the path.
shortbegin="" # The shortened beginning of the path.
current="" # The section of the path we're currently working on.
end="${2:-$(pwd)}/" # The unmodified rest of the path.
if [[ "$end" =~ "$HOME" ]]; then
INHOME=1
end="${end#$HOME}" #strip /home/username from start of string
begin="$HOME" #start expansion from the right spot
else
INHOME=0
fi
end="${end#/}" # Strip the first /
shortenedpath="$end" # The whole path, to check the length.
maxlength="${1:-0}"
shopt -q nullglob && NGV="-s" || NGV="-u" # Store the value for later.
shopt -s nullglob # Without this, anything that doesn't exist in the filesystem turns into */*/*/...
while [[ "$end" ]] && (( ${#shortenedpath} > maxlength ))
do
current="${end%%/*}" # everything before the first /
end="${end#*/}" # everything after the first /
shortcur="$current"
shortcurstar="$current" # No star if we don't shorten it.
for ((i=${#current}-2; i>=0; i--)); do
subcurrent="${current:0:i}"
matching=("$begin/$subcurrent"*) # Array of all files that start with $subcurrent.
(( ${#matching[*]} != 1 )) && break # Stop shortening if more than one file matches.
shortcur="$subcurrent"
shortcurstar="$subcurrent*"
done
#advance
begin="$begin/$current"
shortbegin="$shortbegin/$shortcurstar"
shortenedpath="$shortbegin/$end"
done
shortenedpath="${shortenedpath%/}" # strip trailing /
shortenedpath="${shortenedpath#/}" # strip leading /
if [ $INHOME -eq 1 ]; then
echo "~/$shortenedpath" #make sure it starts with ~/
else
echo "/$shortenedpath" # Make sure it starts with /
fi
shopt "$NGV" nullglob # Reset nullglob in case this is being used as a function.
此外,这是我在我的.bashrc文件中添加的一些函数,用于缩短shell显示的路径。我不确定像这样编辑$PWD是否完全安全,因为某些脚本可能依赖于有效的$PWD字符串,但到目前为止,我偶尔使用并没有出现问题。请注意,我将上面的脚本保存为“shortdir”并将其放在了我的PATH中。
function tinypwd(){
PWD=`shortdir`
}
function hugepwd(){
PWD=`pwd`
}
编辑于2010年10月19日
在bash中进行别名的正确方法是修改变量$PS1
,这是提示符的解析方式。在绝大多数情况下(99%的情况下),当前路径在提示字符串中表示为"\w"。我们可以使用sed将其替换为shortdir
,如下所示:
#NOTE: trailing space before the closing double-quote (") is a must!!
function tinypwd(){
PS1="$(echo $PS1 | sed 's/\\w/\`shortdir\`/g') "
}
function hugepwd(){
PS1="$(echo $PS1 | sed 's/[`]shortdir[`]/\\w/g') "
}
#!/usr/bin/env python
import sys
try:
path = sys.argv[1]
length = int(sys.argv[2])
except:
print >>sys.stderr, "Usage: $0 <path> <length>"
sys.exit(1)
while len(path) > length:
dirs = path.split("/");
# Find the longest directory in the path.
max_index = -1
max_length = 3
for i in range(len(dirs) - 1):
if len(dirs[i]) > max_length:
max_index = i
max_length = len(dirs[i])
# Shorten it by one character.
if max_index >= 0:
dirs[max_index] = dirs[max_index][:max_length-3] + ".."
path = "/".join(dirs)
# Didn't find anything to shorten. This is as good as it gets.
else:
break
print path
示例输出:
$ echo $DIR
/this/is/the/path/to/a/really/long/directory/i/would/like/shortened
$ ./shorten.py $DIR 70
/this/is/the/path/to/a/really/long/directory/i/would/like/shortened
$ ./shorten.py $DIR 65
/this/is/the/path/to/a/really/long/direc../i/would/like/shortened
$ ./shorten.py $DIR 60
/this/is/the/path/to/a/re../long/di../i/would/like/shortened
$ ./shorten.py $DIR 55
/t../is/the/p../to/a/r../l../di../i/wo../like/shortened
$ ./shorten.py $DIR 50
/t../is/the/p../to/a/r../l../d../i/w../l../shortened
PS1="\[\e[31m\]\H:\[\e[32m\]"'`path-shorten $PWD 50`'"\[\e[31m\] -->\[\e[0m\] "
- user195709#!/bin/bash
# Modified from https://dev59.com/WnI-5IYBdhLWcg3w6dC1#1617048
# By Alan Christopher Thomas (http://alanct.com)
__pwd_ps1 ()
{
begin=""
homebegin=""
shortbegin=""
current=""
end="${2:-$(pwd)}/" # The unmodified rest of the path.
end="${end#/}" # Strip the first /
shortenedpath="$end"
shopt -q nullglob && NGV="-s" || NGV="-u"
shopt -s nullglob
while [[ "$end" ]]
do
current="${end%%/*}" # Everything before the first /
end="${end#*/}" # Everything after the first /
shortcur="$current"
for ((i=${#current}-2; i>=0; i--))
do
[[ ${#current} -le 20 ]] && [[ -z "$end" ]] && break
subcurrent="${current:0:i}"
matching=("$begin/$subcurrent"*) # Array of all files that start with $subcurrent
(( ${#matching[*]} != 1 )) && break # Stop shortening if more than one file matches
[[ -z "$end" ]] && shortcur="$subcurrent..." # Add character filler at the end of this string
[[ -n "$end" ]] && shortcur="$subcurrent+" # Add character filler at the end of this string
done
begin="$begin/$current"
homebegin="$homebegin/$current"
[[ "$homebegin" =~ ^"$HOME"(/|$) ]] && homebegin="~${homebegin#$HOME}" # Convert HOME to ~
shortbegin="$shortbegin/$shortcur"
[[ "$homebegin" == "~" ]] && shortbegin="~" # Use ~ for home
shortenedpath="$shortbegin/$end"
done
shortenedpath="${shortenedpath%/}" # Strip trailing /
shortenedpath="${shortenedpath#/}" # Strip leading /
[[ ! "$shortenedpath" =~ ^"~" ]] && printf "/$shortenedpath" # Make sure it starts with /
[[ "$shortenedpath" =~ ^"~" ]] && printf "$shortenedpath" # Don't use / for home dir
shopt "$NGV" nullglob # Reset nullglob in case this is being used as a function.
}
在此处下载脚本并将其包含在你的 .bashrc
文件中:
https://raw.github.com/alanctkc/dotfiles/master/.bash_scripts/pwd-prompt.bash
. ~/.bash_scripts/pwd-prompt.bash
将目录添加到您的PS1
中,方法如下:
export PS1="[other stuff...] \$(__pwd_ps1)\$ "
这里有一个相对简单的Perl解决方案。它足够短,可以直接嵌入PS1而不是调用脚本。它会给出所有被截断名称的字符,而不是用“.”替换。
$ echo '/this/is/a/realy/long/path/id/like/shortened' | perl -F/ -ane 'print join( "/", map { $i++ < @F - 2 ? substr $_,0,3 : $_ } @F)' /thi/is/a/rea/lon/pat/id/like/shortened
我没有立即看到一种好的方法来用“.”替换字符,但这里有一个丑陋的方法:
echo '/this/is/a/realy/long/path/id/like/shortened' | perl -F/ -ane 'print join( "/", map { m/(.)(.*)/; $_ = $1 . "." x (length $2 > 2 ? 2 : length $2 ) if $i++ < @F - 2; $_ } @F)' /t../i./a/r../l../p../i./like/shortened
试试这个:
PS1='$(pp="$PWD/" q=${pp/#"$HOME/"/} p=${q%?};((${#p}>19))&&echo "${p::9}…${p:(-9)}"||echo "$p") \$'
它转换了
~/.vim/bundle/ack.vim/plugin
至
.vim/bund…im/plugin
转换
/usr/share/doc/xorg-x11-font-utils-7.5/
到
/usr/shar…utils-7.5
当$PWD
与$HOME
相同时,不显示任何内容。
奖励:您可以修改长度的数量以适应您的需求。
like/shortened
。我使用ZSH,但是我不知道如何在bash中实现这一点。 - pavpanchekhapwd | sed -e "s|.*/\(.*/.*\)|\1|"
- polypus74function pwd_depth_limit_2 { if [ "$PWD" = "$HOME" ] then echo -n "~" else pwd | sed -e "s|.*/\(.*/.*\)|\1|" fi }
- polypus74