Bash 为什么要在两个实例中创建此符号链接

Bash 为什么要在两个实例中创建此符号链接,bash,zsh,Bash,Zsh,我有一个用于我的dot文件的安装脚本。我正在使用创建一个目录到我的主文件夹的符号链接。链接执行良好,但第二个符号链接被创建,我无法解释为什么 项目中的文件夹结构如下所示 install.sh scripts/ shell.sh shell/ install.sh调用shell.sh并调用命令 ln -s $SCRIPTS_DIR/shell/ $HOME/.shell $SCRIPTS\u DIR是完整路径 所以我的主目录中有一个.shell目录链接得很好,但现在我的项目文件夹有一个

我有一个用于我的dot文件的安装脚本。我正在使用创建一个目录到我的主文件夹的符号链接。链接执行良好,但第二个符号链接被创建,我无法解释为什么

项目中的文件夹结构如下所示

install.sh
scripts/
    shell.sh
shell/
install.sh
调用
shell.sh
并调用命令

ln -s $SCRIPTS_DIR/shell/ $HOME/.shell
$SCRIPTS\u DIR是完整路径

所以我的主目录中有一个.shell目录链接得很好,但现在我的项目文件夹有一个额外的符号链接

install.sh
scripts/
    shell -> PATH_TO_PROJECT/shell
    shell.sh 
shell/

任何解释都将不胜感激

请思考当目标是目录而不是文件时,两次运行
ln-s
命令会发生什么

如果
$HOME/.shell
不存在,则

ln -s "$SCRIPTS_DIR/shell/" "$HOME/.shell"
…创造了它。然而,如果它已经存在,那么

ln -s "$SCRIPTS_DIR/shell/" "$HOME/.shell"
…将
.shell
视为目标目录名,而不是要创建的目标的完整路径,并在该目录中创建一个新条目


GNU
ln
有一些扩展来修复此用法,包括:

-h如果目标_文件或目标_目录是符号链接,请不要跟随它。这对于-f选项非常有用,可以替换可能指向目录的符号链接

因此,如果在GNU系统上操作,您可以使用:

# quotes added for bash compatibility, since question is tagged for both shells
ln -sfh "$SCRIPTS_DIR/shell/" "$HOME/.shell"

否则,请先检查:

[[ -e $HOME/.shell ]] || ln -s "$SCRIPTS_DIR/shell/" "$HOME/.shell"

这不是zsh问题--
ln-s
在任何shell中都会以这种方式运行,如果没有提供GNU扩展名
-h
-n
。顺便说一句,对于用户定义的变量,例如
SCRIPTS\u DIR
,所有caps变量名都不是好的形式;在环境变量(shell变量与之共享一个名称空间)中,所有CAP名称都是为内置变量和修改系统操作的环境变量名称保留的。请参阅BTW的第四段,您给出的代码仅适用于zsh,而不适用于bash(需要更多引号),这或许说明了两个shell的标记是多么糟糕。@charlesduff感谢链接,我已将所有应用程序变量移到小写。你说需要更多的报价是什么意思?在我的bash和zsh shellsTry上,它似乎工作得很好,使
scripts\u dir
指向一个名称中带有空格的目录,您将看到它在bash中失败(或任何符合POSIX的shell;这在zsh中工作只是因为zsh违反了标准)。