我正在寻找一种方法来实现一个响应式工作目录,我至少想要显示第一个和最后一个文件夹.它应该基于终端中的可用.例如$(expr
tput cols之类的东西- 35)}
.
想象一下当前的工作目录是什么 ~/workspace/i/keep/my/projects/project1/src
然后我想显示提示,如:
~/workspace/../src
如果终端足够大我想拥有:
~/workspace/../project1/src
要么
~/workspace/../projects/project1/src
~/workspace/../my/projects/project1/src
所以前进.
如果有足够的地方,它甚至应该显示完整的路径.为了赢得空间,家庭目录应始终显示为~
.
这是否可以在OSX上使用纯bash脚本?
Joh*_*024 13
我想显示提示,如:
~/workspace/../src
这将在使用通常$
和空格结束提示时显示该路径样式:
PS1='$(pwd | sed -E -e "s|^$HOME|~|" -e '\''s|^([^/]*/[^/]*/).*(/[^/]*)|\1..\2|'\'') \$ '
Run Code Online (Sandbox Code Playgroud)
虽然我的目的是在OSX的BSD上进行这项工作sed
,但我只在Linux上使用GNU进行了测试sed
.
此版本仅提供一种输出格式.随着终端变宽,它不会改变格式.
新定义中的关键元素PS1
是命令替换.那个命令是:
pwd | sed -E -e "s|^$HOME|~|" -e 's|^([^/]*/[^/]*/).*(/[^/]*)|\1..\2|'
Run Code Online (Sandbox Code Playgroud)
pwd
这会将当前工作目录打印到stdout
"s|^$HOME|~|"
如果路径开头$HOME
,请将其替换为~
.因为$HOME
是shell变量,所以此命令必须是双引号,以便shell执行变量替换$HOME
.
's|^([^/]*/[^/]*/).*(/[^/]*)|\1..\2|'
正则表达式由三部分组成:
^([^/]*/[^/]*/)
匹配前两个目录并将其保存\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;}'\'') \$ '
Run Code Online (Sandbox Code Playgroud)
因为此解决方案需要更多计算,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;}'
Run Code Online (Sandbox Code Playgroud)
代码考虑了这些情况:
目录字符串已经足够短了.换句话说,它的长度适合分配的空间.在这种情况下,它按原样显示.
只有三个目录.例如,~/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;}
如果我们得到,那么我们的目录字符串需要缩短.因此,我们将缩写字符串添加/../
到末尾b
.对于第一次试验,我们将结束字符串设置e
为最后一个目录.(在awk
,NF
是字段的数量.因此,$NF
是最后一个字段(目录)就行了.)然后,我们从减去n
的长度b
和e
.n
剩下的价值是我们剩下的空间量.然后从该行的倒数第二个目录开始,我们尝试一次添加一个目录,e
而不会超过我们的目标,即目录字符串应该有多长.
{print b e;}
这将打印提示中使用的最终目录字符串.
要更改目录显示所占用的空间量,我们将读取的命令n=0.3*n
(目标为30%宽度)更改为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;}'\'') \$ '
Run Code Online (Sandbox Code Playgroud)
根据您的喜好,您可能需要其他公式.例如,尝试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\$ '
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
2156 次 |
最近记录: |