为什么此Shell脚本中包含反斜杠?


21

conda.sh脚本的副本中,我看到以下几行:

if [ -n "${_CE_CONDA}" ] && [ -n "${WINDIR+x}" ]; then
    SYSP=$(\dirname "${CONDA_EXE}")
else
    SYSP=$(\dirname "${CONDA_EXE}")
    SYSP=$(\dirname "${SYSP}")
fi

我很好奇,为什么在前面的一个反斜杠ddirname。我认为没有必要。反斜杠的这种用法也出现在源文件的其他位置。我有没有这样做的理由?


Answers:


30

反斜杠将抑制别名扩展,即,它执行原始命令并确保别名版本不运行。当系统已设置shopt -s expand_aliases(仅BASH)或使用来执行脚本时,脚本会在不知不觉中以别名扩展方式运行source

./conda.sh          # usually no alias expansion (unless `shopt -s expand_aliases` in BASH)
source ./conda.sh   # alias expansion
. ./conda.sh        # alias expansion

一些系统管理员喜欢在所有内容中都加反斜杠,以防止别名的副作用,以防万一它在其他地方被无意地使用了别名并且别名得到了扩展(如前所述)。例如,如果系统在alias dirname='dirname -z'某个地方设置了此名称,并且条件允许扩展别名,那么不幸的是,尝试调用dirname的脚本将dirname -z改为调用,这不是该脚本的目的。

如果可以确定这样的别名不存在,我们可以删除所有的反斜杠,并且应该可以正常工作。

或者,可以使用command而不是反斜杠版本来抑制别名。因此,\dirname可以使用代替command dirname,它看起来更易读。(对于诸如的内置命令cd,应builtin改为使用)。我更喜欢它,因为它也绕过了具有相同名称以及任何别名的函数。


1
另外值得注意的是unalias -a,它会删除所有别名。
Centimane

19
@Centimane是的,但请确保\unalias -a抑制别名扩展
Ben C

sysadmin也可以写/usr/bin/dirname吗?
罗恩·约翰

@RonJohn是的,在这种情况下,他可能会遇到。但是,对于某些程序,不同的发行版将它们放在不同的目录中。我想到的一个实例是/bin/edUbuntu与/usr/bin/edCentOS。放置完整路径会降低脚本的可移植性。
donal24

@ doneal24怎么样DIRNAME=$(which dirname),因为which看不到别名?
罗恩·约翰

20

如果conda.sh是要获取的文件,则反斜杠用于绕过别名。Bash通常为脚本执行禁用别名扩展,但是对于可能在交互式Shell中运行的源文件,则不是这种情况。因此,dirname可能只运行一个名为的别名dirname,但\dirname会跳过别名扩展,而运行一个名为的函数或命令dirname。(不过,不只是反斜杠,任何引用都可以。)


5
或者command dirname
库沙兰南达

7
\command dirname,以防万一有人也为其别名command。):|
穆鲁

为什么绕过别名?此功能是某物的特例,还是必须将其硬编码到bash中(即黑客)?
Extremeaxe5

@ extremeaxe5 bash如果引用了单词的任何部分,则不会进行别名扩展。
穆鲁

1
@ extremeaxe5如果您要问为什么该功能根本存在,我不知道。但是,它在POSIX标准中:“应检查命令名单词[...]以确定它是否是未引用的有效别名”
muru
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.