从 Fish 中的路径中提取文件夹名称 Shell
Extracting a folder name from path in Fish Shell
我有多个这样的目录
~/project/foo/Debug
~/project/bar/Debug
... and so on
文件夹 project
和 Debug
是常量。
我在调试目录中,foo
和bar
是项目名称。当我在 ~/project/bar/Debug
中时,是否可以将变量设置为字符串 bar
,当我在目录 ~/project/xxxxx/Debug
中时,是否可以将该变量设置为 xxxxx
?
当前目录可通过 PWD
变量获得,因此您可以测试:
set -g string # define variable globally
if test $PWD = ~/project/foo/Debug
set string foo
else if test $PWD = ~/project/bar/Debug
set string bar
end
当然,如果项目超过三个,或者列表随时间发生变化,那会变得很笨重,所以你可以使用 fish 内置的 string
工具对其进行匹配和替换。
set -g string
if string match -q '/projects/*/Debug'
set string (string replace -r '.*/projects/([^/]+)/Debug' '' -- $PWD)
end
我怀疑您真正想要的是在提示中显示您的项目名称而不是工作目录。如果是这样并且你使用git,你可以使用这个
function prompt_pwd --description 'Print the current working directory, shortened to fit the prompt'
set -q argv[1]; and switch $argv[1]
case -h --help
__fish_print_help prompt_pwd
return 0
end
# This allows overriding fish_prompt_pwd_dir_length from the outside (global or universal) without leaking it
set -q fish_prompt_pwd_dir_length; or set -l fish_prompt_pwd_dir_length 1
set -l tmp
set -l gitdir
# Replace everything up to the vcs root with [rootname]
# under the assumption that that is the name of the "project".
# TODO: On my machine, it seems that the last two components are the safer bet, e.g.
# kwin/tiling
# exercism/cli (go)
# elves/elvish (go)
# new/exa-git (aur)
# dev/fish-shell
#
# Either that, or a more robust system of abbreviations,
# a non-hacky solution for which needs dictionaries.
if set gitdir (git rev-parse --show-toplevel ^/dev/null)
set tmp (string replace -- $gitdir '' $PWD)
# Underline the "project name"
# FIXME: The coloring here will leak, but I can't see a way to just undo underlining.
set gitdir \[(set_color -u)(string replace -r '.*/' '' -- $gitdir)(set_color normal; set_color $fish_color_cwd)\]
else
# Replace $HOME with "~"
# Only if we're not in a gitdir, otherwise $HOME/dev/$HOME would give weird results.
set realhome ~
# FIXME: This will give weird results if any special regex chars are in $HOME,
# but it should be a regex match because we only want it replaced at the beginning of the string.
set tmp (string replace -r '^'"$realhome"'($|/)' '~' $PWD)
end
# The test will return false if $fish_... is non-numerical,
# and the replace will not replace anything, so the PWD will be unshortened.
# This is okay.
if [ $fish_prompt_pwd_dir_length -eq 0 ]
echo -s $gitdir $tmp
else
# Shorten to at most $fish_prompt_pwd_dir_length characters per directory
# but only after the gitdir
echo "$gitdir"(string replace -ar '(\.?[^/]{'"$fish_prompt_pwd_dir_length"'})[^/]*/' '/' $tmp)
end
end
这也可以适用于例如mercurial 或类似的,虽然根据我的经验,mercurial 启动起来相当慢,因此不是你希望每次提示都发生的事情。
保存在~/.config/fish/functions/prompt_pwd.fish.
正如 faho 在他的回答中指出的那样,如果效率至关重要,则可以使用最近添加的 string
内置函数。但是,在这种情况下,我可能会使用传统的解决方案,因为它的清晰度和简单性:
set var (basename (dirname $PWD))
如果您不想支付两个非常便宜的外部命令的费用,我会这样做而不是使用正则表达式:
set components (string split -- / $PWD)
set var $components[-2]
您甚至可以在一条语句中做到这一点:
set var (string split -- / $PWD)[-2]
我有多个这样的目录
~/project/foo/Debug
~/project/bar/Debug
... and so on
文件夹 project
和 Debug
是常量。
我在调试目录中,foo
和bar
是项目名称。当我在 ~/project/bar/Debug
中时,是否可以将变量设置为字符串 bar
,当我在目录 ~/project/xxxxx/Debug
中时,是否可以将该变量设置为 xxxxx
?
当前目录可通过 PWD
变量获得,因此您可以测试:
set -g string # define variable globally
if test $PWD = ~/project/foo/Debug
set string foo
else if test $PWD = ~/project/bar/Debug
set string bar
end
当然,如果项目超过三个,或者列表随时间发生变化,那会变得很笨重,所以你可以使用 fish 内置的 string
工具对其进行匹配和替换。
set -g string
if string match -q '/projects/*/Debug'
set string (string replace -r '.*/projects/([^/]+)/Debug' '' -- $PWD)
end
我怀疑您真正想要的是在提示中显示您的项目名称而不是工作目录。如果是这样并且你使用git,你可以使用这个
function prompt_pwd --description 'Print the current working directory, shortened to fit the prompt'
set -q argv[1]; and switch $argv[1]
case -h --help
__fish_print_help prompt_pwd
return 0
end
# This allows overriding fish_prompt_pwd_dir_length from the outside (global or universal) without leaking it
set -q fish_prompt_pwd_dir_length; or set -l fish_prompt_pwd_dir_length 1
set -l tmp
set -l gitdir
# Replace everything up to the vcs root with [rootname]
# under the assumption that that is the name of the "project".
# TODO: On my machine, it seems that the last two components are the safer bet, e.g.
# kwin/tiling
# exercism/cli (go)
# elves/elvish (go)
# new/exa-git (aur)
# dev/fish-shell
#
# Either that, or a more robust system of abbreviations,
# a non-hacky solution for which needs dictionaries.
if set gitdir (git rev-parse --show-toplevel ^/dev/null)
set tmp (string replace -- $gitdir '' $PWD)
# Underline the "project name"
# FIXME: The coloring here will leak, but I can't see a way to just undo underlining.
set gitdir \[(set_color -u)(string replace -r '.*/' '' -- $gitdir)(set_color normal; set_color $fish_color_cwd)\]
else
# Replace $HOME with "~"
# Only if we're not in a gitdir, otherwise $HOME/dev/$HOME would give weird results.
set realhome ~
# FIXME: This will give weird results if any special regex chars are in $HOME,
# but it should be a regex match because we only want it replaced at the beginning of the string.
set tmp (string replace -r '^'"$realhome"'($|/)' '~' $PWD)
end
# The test will return false if $fish_... is non-numerical,
# and the replace will not replace anything, so the PWD will be unshortened.
# This is okay.
if [ $fish_prompt_pwd_dir_length -eq 0 ]
echo -s $gitdir $tmp
else
# Shorten to at most $fish_prompt_pwd_dir_length characters per directory
# but only after the gitdir
echo "$gitdir"(string replace -ar '(\.?[^/]{'"$fish_prompt_pwd_dir_length"'})[^/]*/' '/' $tmp)
end
end
这也可以适用于例如mercurial 或类似的,虽然根据我的经验,mercurial 启动起来相当慢,因此不是你希望每次提示都发生的事情。
保存在~/.config/fish/functions/prompt_pwd.fish.
正如 faho 在他的回答中指出的那样,如果效率至关重要,则可以使用最近添加的 string
内置函数。但是,在这种情况下,我可能会使用传统的解决方案,因为它的清晰度和简单性:
set var (basename (dirname $PWD))
如果您不想支付两个非常便宜的外部命令的费用,我会这样做而不是使用正则表达式:
set components (string split -- / $PWD)
set var $components[-2]
您甚至可以在一条语句中做到这一点:
set var (string split -- / $PWD)[-2]