我正在寻找一种实现响应式工作目录的方法,我至少想要显示第一个和最后一个文件夹。
它应该基于终端中的可用。例如。例如$(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脚本?
答案 0 :(得分:12)
我想显示提示,例如:
~/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
。
如果有足够的目录供正则表达式匹配,则整个路径将替换为\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;}
如果我们得到,那么我们的目录字符串需要缩短。因此,我们将缩写字符串/../
添加到b
的末尾。对于第一次试验,我们将结束字符串e
设置为最后一个目录。 (在awk
中,NF
是字段数。因此,$NF
是该行的最后一个字段(目录)。)然后我们从n
中减去b
的长度。 e
和n
。剩下的e
的值是我们剩下的空间量。然后从该行的倒数第二个目录开始,我们尝试一次将一个目录添加到{print b e;}
,而不会超过目标字符串应该达到的目标。
n=0.3*n
这将打印提示中使用的最终目录字符串。
要更改目录显示占用的空间量,我们将读取n=1*n
(目标为30%宽度)的命令更改为$
(即使是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\$ '
(换行符):
{{1}}
答案 1 :(得分:0)
我创建了一个基本脚本(仍然需要一些增强功能来完成最后的计算路径,以找出在&#34;〜/ worksapce /../之后要显示多少部分(最后部分或后缀部分) ;(fpart或第一部分或前缀),否则,如果您符合以下条件,它将起作用:
1.出口栏目和
< strong> 2.设置你的PS1 为&#34; *导出PS1 =&#34;`〜/ somedir / koba.sh` $&#34;
当你的COLUMNS值小于echo ~/workspace | wc -c
时,我也测试了〜/ workspace文件夹的条件。此基本示例脚本仅将lpart / suffix / last部分作为最后一个文件夹(因为我使用basename命令)。唯一的另一件事,我看到的是,我每次都必须导出PS1(在最小化/最大化窗口之后,但之后它按预期工作)。
[giga @ someserver somePS1] $ cat~ / somedir / koba.sh
#!/bin/bash
## NOTE this script should echo only 1 echo output and exit out as soon as you echo
## your first echo.
cdir=`pwd`
wc_dir=$(echo $cdir | wc -c)
bal=$(expr $COLUMNS - $wc_dir)
if [[ "`echo $(pwd) | tr '/' '\012'| wc -l`" -le 2 || $bal -ge $wc_dir ]];
then
echo "`pwd`"; exit 0 ;
else
fpart="$(echo $cdir | cut -d'/' -f1,2)/../"
lpart="$(basename $cdir)"
## Calculate lpart (last part) in an better way to show ../aaa or ../aaa/bbb or ../aaa/bbb/c1 or more depending upon $COLUMNS and $wc_dir
## Do that math here.
## ...
## ...
echo "${fpart}${lpart}"; exit 0;
fi
或强>
导出这2个ENV变量后。如果你:
只需将以下ENVIRONMENT变量设置为脚本即可。每次显示PS1之前,此变量都会调用脚本。因此,它设置dir值,PS1设置为以给定格式显示。使用此功能,现在每次更改窗口/屏幕大小时, NOT 都必须重置PS1,或者在路径中移动到不同的父/子文件夹。只需按Enter键(最小化/最大化窗口),看看它有效!!!
export PROMPT_COMMAND="~/somedir/koba.sh"