最简单情况的解决方案
我想要显示类似于这样的提示:~/workspace/../src
这将以通常的$
和空格结束提示,同时显示该路径样式:
PS1='$(pwd | sed -E -e "s|^$HOME|~|" -e '\''s|^([^/]*/[^/]*/).*(/[^/]*)|\1..\2|'\'') \$ '
尽管我的意图是针对OSX的BSD版
sed
进行这项工作,但我只在使用GNU版
sed
的Linux上进行了测试。
此版本仅提供一种输出格式。 它不会随着终端变宽而更改格式。
它是如何工作的
定义新的
PS1
中的关键元素是命令替换。该命令为:
pwd | sed -E -e "s|^$HOME|~|" -e 's|^([^/]*/[^/]*/).*(/[^/]*)|\1..\2|'
pwd
此命令将当前工作目录打印到标准输出(stdout)。
"s|^$HOME|~|"
如果路径以$HOME
开头,则将其替换为~
。由于$HOME
是shell变量,因此此命令必须用双引号括起来,以便Shell对$HOME
进行变量替换。
's|^([^/]*/[^/]*/).*(/[^/]*)|\1..\2|'
正则表达式由三部分组成:
如果存在足够多的目录以使正则表达式匹配,那么整个路径将被替换为\1..\2
。
更复杂的解决方案
假设我们希望提示符的格式随终端可用宽度而改变,如果有空间的话,则显示更多的最终目录。因此,在窄终端中,/home/user/dir1/dir2/dir3/dir4
可能会显示为~/dir1/../dir4
,但在宽终端中,它将显示为~/dir1/../dir3/dir4
,而在仍然较宽的终端中,它将显示为~/dir1/dir2/dir3/dir4
。
在这种情况下:
PS1='$(pwd|awk -F/ -v "n=$(tput cols)" -v "h=^$HOME" '\''{sub(h,"~");n=0.3*n;b=$1"/"$2} length($0)<=n || NF==3 {print;next;} NF>3{b=b"/../"; e=$NF; n-=length(b $NF); for (i=NF-1;i>3 && n>length(e)+1;i--) e=$i"/"e;} {print b e;}'\'') \$ '
由于这种解决方案需要更多的计算,所以使用了awk
。
该代码允许用户调整目录列表占终端宽度的比例。这可以通过调整代码中的常量n=0.3*n
来实现。如写就只限制目录显示在终端宽度的30%。
工作原理
该代码的关键元素是以下命令:
pwd | awk -F/ -v "n=$(tput cols)" -v "h=^$HOME" '{sub(h,"~");n=0.3*n;b=$1"/"$2} length($0)<=n || NF==3 {print;next;} NF>3{b=b"/../"; e=$NF; n-=length(b $NF); for (i=NF-1;i>3 && n>length(e)+1;i--) e=$i"/"e;} {print b e;}'
代码考虑以下情况:
- 目录字符串本来就很短,长度适合所分配的空间。这种情况下,它将按原样显示。
- 只有三个目录。例如,
~/dir1/dir2
。我们的格式不允许缩短它。因此,在这种情况下,目录字符串将按原样显示。
- 有四个或更多目录,并且必须缩短目录字符串以适应空间。在这种情况下,目录字符串被分成两部分:开头存储在变量
b
中,结尾存储在变量e
中。开头包含两个目录和点-点字符串,例如~/dir1/../
。从最后一个目录开始,只要空间允许,目录就会添加到结尾字符串e
中。
awk
命令的更多细节
-F /
这将字段分隔符设置为/
。因此,每个目录将出现为单独的字段。
-v "n=$(tput cols)" -v "h=^$HOME"
这创建了我们需要的两个变量。 n
是终端宽度(以列为单位)。 h
是匹配用户主目录的正则表达式。
sub(h,"~")
如果路径以用户主目录开头,则将其替换为~
。
n = 0.3 * n
这为提示中所需目录字符串的期望宽度设置了一个目标。我喜欢目录字符串不要太长,因此n = 0.3 * n
将目标设置为终端宽度的30%(以列为单位)。如其他地方讨论的那样,可以根据个人偏好替换为另一个公式。
b = $1"/"$2
b
是包含目录字符串开头部分的变量。在这里,我们将其设置为前两个目录。例如,如果路径是~/dir1/dir2/dir3
,那么这将把b
设置为~/dir1
。
length($0)<=n || NF==3 {print;next;}
如果完整的目录字符串不超过我们的目标长度n
,或者目录字符串中只有三个目录,则按原样打印目录字符串,然后退出。
NF>3{b=b"/../"; e=$NF; n-=length(b $NF); for (i=NF-1;i>3 && n>length(e)+1;i--) e=$i"/"e;} print b e;
This code shortens the directory string if it exceeds a certain length, by removing directories and replacing them with /../
. The shortened string is then printed as the final directory string in the command prompt. To change the width of the display, the command n=0.3*n
should be replaced with n=1*n
.
PS1='$(pwd|awk -F/ -v "n=$(tput cols)" -v "h=^$HOME" '\''{sub(h,"~");n=1*n;b=$1"/"$2} length($0)<=n || NF==3 {print;next;} NF>3{b=b"/../"; e=$NF; n-=length(b $NF); for (i=NF-1;i>3 && n>length(e)+1;i--) e=$i"/"e;} {print b e;}'\'') \$ '
根据您的个人偏好,您可能需要其他公式。例如,尝试n=n-10
,它将尝试在提示符末尾留下一些(但不是很多)可用的空间。
PM2Ring建议将$
提示符始终放置在下一行,在此之前,我们需要在\$
提示符之前插入一个换行符\n
:
PS1='$(pwd|awk -F/ -v "n=$(tput cols)" -v "h=^$HOME" '\''{sub(h,"~");n=1*n;b=$1"/"$2} length($0)<=n || NF==3 {print;next;} NF>3{b=b"/../"; e=$NF; n-=length(b $NF); for (i=NF-1;i>3 && n>length(e)+1;i--) e=$i"/"e;} {print b e;}'\'') \n\$ '
~/somedir/koba.sh
> "。然后创建此脚本(koba.sh)或任何您喜欢的名称。在该脚本中,使用pwd
并只使用一个“echo”语句来回显您想要的格式/workspace/../xx/zz"或者计算您想要作为输出回显的内容(它将考虑会话窗口的环境变量COLUMNS的值),即每次使用鼠标最小化/最大化屏幕大小时都应更改PS1。需要注意的一个重要点是,如果您在/workspace文件夹中,则您的PS1不应回显~/../workspace。 - AKS\n
。解放啊! :) - PM 2Ring