在 ZSH 中,..
相当于cd ..
感谢auto_cd
,如果我不得不猜测(我完全是猜测)它是某种别名。
然而,在许多其他*sh
(ash
至少bash
)中,此功能尚未实现。
在ash
,你得到
willard@willardsworld:~/.ssh# ..
-ash: ..: Permission denied
这太奇怪了。如果我不得不猜测(再次猜测),这是一个权限错误,因为root
拥有该目录。
willard@willardsworld:~/.ssh# ls -la
drwxr-xr-x 3 root root 4096 May 22 16:06 .
drwxr-xr-x 21 root root 4096 May 22 15:03 ..
drwx------ 2 root root 4096 May 26 11:37 .ssh
但是,它仍然不能正常工作root
。
root@willardsworld:~/.ssh# ..
-ash: ..: Permission denied
这又是胡扯。root
拥有..
,对吧?
将此行为与bash
你只需获得的行为进行比较
willard@willardsworld:~/.ssh$ ..
..: command not found
这完全说得通。该功能根本不存在。
我想知道的是,ZSH 是如何auto_cd
工作的,以及为什么会ash
出现权限错误?
答案1
这只是对原因的合理猜测,但以下是可能发生的情况。当您使用不包含“ /
”的命令名称(即,它只是一个名称,而不是显式路径)时,shell 将检查它是别名、函数还是内置函数,如果不是其中任何一个,它将在目录中将其作为可执行文件进行查找$PATH
。因此,该过程大致如下:
检查“
..
”是否是别名,函数,还是内置函数:不是。假设中的第一个目录
$PATH
是/bin
。检查它是否/bin/..
存在于文件系统中:是的,它确实!每个目录都包含一个名为“ ”的项目
..
,它是文件系统中其父目录的链接,因此/bin/..
也是 的链接/
。尝试执行
/bin/..
,但失败了,因为它是一个目录而不是可执行文件。(您可以cd
执行到目录,但这与执行它完全不同。)
现在,这并不能解释为什么你得到的是“权限被拒绝”错误,而不是某种“这不是可执行文件”错误,所以我可能是错的。在ash
你的操作系统上,尝试/bin/..
以显式命令运行,看看你得到的错误消息是什么。
答案2
Bash 肯定使用了一些防御性编程,它识别出“..”是一个目录,因此拒绝运行它。ash,只会调用 execve(2) 或类似程序并返回由此产生的操作系统错误。以下 3 行 C 代码将发出“权限被拒绝”:
char *args[] = { "..", 0 };
execve("..", args, 0);
perror(0);
execve(2) 的手册页列出了对 EACCES 的多种解释。
zsh 功能未实现为别名。别名扩展很早就应用了。它与可执行文件的搜索一起发生。如果你这样做unsetopt autocd
,它会打印“权限被拒绝”。