基于当前目录字符串长度的命令提示符 (PS1) 的设置值
Setting value of command prompt ( PS1) based on present directory string length
我知道我可以这样做来反映 PS1
值中的最后 2 个目录。
PS1=${PWD#"${PWD%/*/*}/"}#
但是假设我们有一个非常混乱的目录名称,会减少我的工作 space ,比如
T-Mob/2021-07-23--07-48-49_xperia-build-20191119010027#
或
2021-07-23--07-48-49_nokia-build-20191119010027/T-Mob#
这些是 prompt
之前的最后两个目录
我想设置条件 如果最后两个目录中的任何一个的目录长度超过阈值,例如10 个字符,用长度超过 10 的目录的前 3 个和后 3 个字符缩短名称
例如
2021-07-23--07-48-49_xperia-build-20191119010027 &
2021-07-23--07-48-49_nokia-build-20191119010027
gt 10 都将缩短为 202*027
& PS1 将分别缩短为
T-Mob/202*027/# for T-Mob/2021-07-23--07-48-49_xperia-build-20191119010027#
和
202*027/T-Mob# for 2021-07-23--07-48-49_nokia-build-20191119010027/T-Mob#
一个快速的 1 Liner 来完成这个?
我不能在评论中 post 这个所以在这里更新。参考 Joaquins Answer ( thx J)
PS1=''`echo ${PWD#"${PWD%/*/*}/"} | awk -v RS='/' 'length() <=10{printf [=15=]"/"}; length()>10{printf "%s*%s/", substr([=15=],1,3), substr([=15=],length()-2,3)};'| tr -d "\n"; echo "#"`''
见下文o/p的
/root/my-applications/bin # it shortened as expected
my-*ons/bin/#cd - # going back to prev.
/root
my-*ons/bin/# #value of prompt is the same but I am in /root
单线基本上总是错误的选择。编写健壮、可读和可维护的代码(并且,对于经常调用或在紧密循环中调用的东西,要高效)——不要简洁。
假设 bash 4.3 或更新版本可用:
# Given a string, a separator, and a max length, shorten any segments that are
# longer than the max length.
shortenLongSegments() {
local -n destVar=; shift # arg1: where do we write our result?
local maxLength=; shift # arg2: what's the maximum length?
local IFS=; shift # arg3: what character do we split into segments on?
read -r -a allSegments <<<""; shift # arg4: break into an array
for segmentIdx in "${!allSegments[@]}"; do # iterate over array indices
segment=${allSegments[$segmentIdx]} # look up value for index
if (( ${#segment} > maxLength )); then # value over maxLength chars?
segment="${segment:0:3}*${segment:${#segment}-3:3}" # build a short version
allSegments[$segmentIdx]=$segment # store shortened version in array
fi
done
printf -v destVar '%s\n' "${allSegments[*]}" # build result string from array
}
# function to call from PROMPT_COMMAND to actually build a new PS1
buildNewPs1() {
# declare our locals to avoid polluting global namespace
local shorterPath
# but to cache where we last ran, we need a global; be explicit.
declare -g buildNewPs1_lastDir
# do nothing if the directory hasn't changed
[[ $PWD = "$buildNewPs1_lastDir" ]] && return 0
shortenLongSegments shorterPath 10 / "$PWD"
PS1="${shorterPath}$"
# update the global tracking where we last ran this code
buildNewPs1_lastDir=$PWD
}
PROMPT_COMMAND=buildNewPs1 # call buildNewPs1 before rendering the prompt
请注意,printf -v destVar %s "valueToStore"
用于就地写入变量,以避免 var=$(someFunction)
的性能开销。类似地,我们正在使用 bash 4.3 功能名称变量——可通过 local -n
或 declare -n
访问——允许目标变量名称被参数化而没有 eval
的安全风险.
如果你真的想让这个逻辑只适用于最后两个目录名(虽然我没有看到为什么会比将它应用于所有这些更好),你可以很容易地做到这一点:
buildNewPs1() {
local pathPrefix pathFinalSegments
pathPrefix=${PWD%/*/*} # everything but the last 2 segments
pathSuffix=${PWD#"$pathPrefix"} # only the last 2 segments
# shorten the last 2 segments, store in a separate variable
shortenLongSegments pathSuffixShortened 10 / "$pathSuffix"
# combine the unshortened prefix with the shortened suffix
PS1="${pathPrefix}${pathSuffixShortened}$"
}
...添加仅在目录更改为此版本时重建 PS1 的性能优化留作 reader.
的练习
可能不是最好的解决方案,但是使用 awk 的快速解决方案:
PS1=`echo ${PWD#"${PWD%/*/*}/"} | awk -v RS='/' 'length()<=10{printf [=10=]"/"}; length()>10{printf "%s*%s/", substr([=10=],1,3), substr([=10=],length()-2,3)};'| tr -d "\n"; echo "#"`
我用你的例子得到了这个结果:
T-Mob/202*027/#
202*027/T-Mob/#
我知道我可以这样做来反映 PS1
值中的最后 2 个目录。
PS1=${PWD#"${PWD%/*/*}/"}#
但是假设我们有一个非常混乱的目录名称,会减少我的工作 space ,比如
T-Mob/2021-07-23--07-48-49_xperia-build-20191119010027#
或
2021-07-23--07-48-49_nokia-build-20191119010027/T-Mob#
这些是 prompt
我想设置条件 如果最后两个目录中的任何一个的目录长度超过阈值,例如10 个字符,用长度超过 10 的目录的前 3 个和后 3 个字符缩短名称 例如
2021-07-23--07-48-49_xperia-build-20191119010027 &
2021-07-23--07-48-49_nokia-build-20191119010027
gt 10 都将缩短为 202*027
& PS1 将分别缩短为
T-Mob/202*027/# for T-Mob/2021-07-23--07-48-49_xperia-build-20191119010027#
和
202*027/T-Mob# for 2021-07-23--07-48-49_nokia-build-20191119010027/T-Mob#
一个快速的 1 Liner 来完成这个?
我不能在评论中 post 这个所以在这里更新。参考 Joaquins Answer ( thx J)
PS1=''`echo ${PWD#"${PWD%/*/*}/"} | awk -v RS='/' 'length() <=10{printf [=15=]"/"}; length()>10{printf "%s*%s/", substr([=15=],1,3), substr([=15=],length()-2,3)};'| tr -d "\n"; echo "#"`''
见下文o/p的
/root/my-applications/bin # it shortened as expected
my-*ons/bin/#cd - # going back to prev.
/root
my-*ons/bin/# #value of prompt is the same but I am in /root
单线基本上总是错误的选择。编写健壮、可读和可维护的代码(并且,对于经常调用或在紧密循环中调用的东西,要高效)——不要简洁。
假设 bash 4.3 或更新版本可用:
# Given a string, a separator, and a max length, shorten any segments that are
# longer than the max length.
shortenLongSegments() {
local -n destVar=; shift # arg1: where do we write our result?
local maxLength=; shift # arg2: what's the maximum length?
local IFS=; shift # arg3: what character do we split into segments on?
read -r -a allSegments <<<""; shift # arg4: break into an array
for segmentIdx in "${!allSegments[@]}"; do # iterate over array indices
segment=${allSegments[$segmentIdx]} # look up value for index
if (( ${#segment} > maxLength )); then # value over maxLength chars?
segment="${segment:0:3}*${segment:${#segment}-3:3}" # build a short version
allSegments[$segmentIdx]=$segment # store shortened version in array
fi
done
printf -v destVar '%s\n' "${allSegments[*]}" # build result string from array
}
# function to call from PROMPT_COMMAND to actually build a new PS1
buildNewPs1() {
# declare our locals to avoid polluting global namespace
local shorterPath
# but to cache where we last ran, we need a global; be explicit.
declare -g buildNewPs1_lastDir
# do nothing if the directory hasn't changed
[[ $PWD = "$buildNewPs1_lastDir" ]] && return 0
shortenLongSegments shorterPath 10 / "$PWD"
PS1="${shorterPath}$"
# update the global tracking where we last ran this code
buildNewPs1_lastDir=$PWD
}
PROMPT_COMMAND=buildNewPs1 # call buildNewPs1 before rendering the prompt
请注意,printf -v destVar %s "valueToStore"
用于就地写入变量,以避免 var=$(someFunction)
的性能开销。类似地,我们正在使用 bash 4.3 功能名称变量——可通过 local -n
或 declare -n
访问——允许目标变量名称被参数化而没有 eval
的安全风险.
如果你真的想让这个逻辑只适用于最后两个目录名(虽然我没有看到为什么会比将它应用于所有这些更好),你可以很容易地做到这一点:
buildNewPs1() {
local pathPrefix pathFinalSegments
pathPrefix=${PWD%/*/*} # everything but the last 2 segments
pathSuffix=${PWD#"$pathPrefix"} # only the last 2 segments
# shorten the last 2 segments, store in a separate variable
shortenLongSegments pathSuffixShortened 10 / "$pathSuffix"
# combine the unshortened prefix with the shortened suffix
PS1="${pathPrefix}${pathSuffixShortened}$"
}
...添加仅在目录更改为此版本时重建 PS1 的性能优化留作 reader.
的练习可能不是最好的解决方案,但是使用 awk 的快速解决方案:
PS1=`echo ${PWD#"${PWD%/*/*}/"} | awk -v RS='/' 'length()<=10{printf [=10=]"/"}; length()>10{printf "%s*%s/", substr([=10=],1,3), substr([=10=],length()-2,3)};'| tr -d "\n"; echo "#"`
我用你的例子得到了这个结果:
T-Mob/202*027/#
202*027/T-Mob/#