因此,目前在 macOS 上我设置了如下别名...
alias ...='cd ../..'
alias ....='cd ../../..'
...
这样我就可以通过在终端中输入来进入多个目录。但是,在我之前的设置中,输入cd ...
会进入多个目录。我cd
一开始就被训练过如何书写……我该如何更改我的别名才能让它按照我想要的方式工作?
答案1
在...的帮助下https://stackoverflow.com/questions/941338/how-to-pass-command-line-arguments-to-a-shell-alias你的问题可以这样解决:
alias cd='function _cd(){ cd ${1/.../..\/..}; }; _cd '
函数中的参数扩展将所有出现的“...”替换为“../..”,因此这不是一个真正干净的解决方案,但我认为它仍然可以接受或可以改进。
答案2
别名不能包含空格。要使用别名执行所需操作,您需要利用此属性:
如果替换单词的别名值以 <blank> 结尾,则 shell 应检查下一个命令字以进行别名替换;此过程应持续,直到找到不是有效别名的单词或别名值不以 <blank> 结尾。
(来源), 所以cd
和连续...
被解析为别名。
您需要这样的别名:
cd='cd '
...='../..'
....='../../..'
# and so on
但是如果你碰巧有一个名为 的目录ls
,并且你输入cd ls
,那么ls
也容易发生别名替换。如果ls
是别名,这将适得其反。
因此,纯别名方法是错误的。此函数将执行(用它没有上述别名):
cd() {
if [ "$#" -eq 0 ]; then
command cd
elif [ "$(printf '%s' "$1" | wc -l)" -eq 0 ]; then
command cd "$(printf '%s' "$1" | sed '/^\.\.\+$/ {s|..|.|; s|.|../|g }')";
else
command cd "$1"
fi
}
(注意:为了使其在 中工作zsh
,请在函数体中调用set -o POSIX_BUILTINS
或替换每个command
) 。builtin
sed
获取传递给函数的参数,并且当且仅当它由两个或多个点组成时才更改它;该工具会删除第一个点并用替换每个点(剩下的)../
。
还有额外的逻辑:
[ "$#" -eq 0 ]
允许鞋底cd
(无参数)正常工作。[ "$(printf '%s' "$1" | wc -l)" -eq 0 ]
是为了防止sed
改变多行目录名称(foo<newline>.....
例如是有效名称)。请注意,对于通常的名称(不包含换行符),wc -l
将返回0
(不是1
,POSIX 不认为没有以换行符结尾的“行”是行),因此我们针对进行测试0
。
还有一个怪癖:
- 前
s|..|.|
两个点不是文字点,这是正则表达式。有人可能会说应该是,s|\.\.|.|
但请注意/^\.\.\+$/
确保行中首先只有点。这同样适用于中的第一个点s|.|../|g
。