为什么在可执行文件或脚本名称之前需要。/(点-斜杠)才能在bash中运行它?

当在bash中运行脚本时,我必须在开始时编写./:

$ ./manage.py syncdb

如果我不这样做,我得到一个错误消息:

$ manage.py syncdb
-bash: manage.py: command not found

这是什么原因呢?我认为.是当前文件夹的别名,因此这两个调用应该是等效的。

我也不明白为什么在运行应用程序时不需要./,例如:

user:/home/user$ cd /usr/bin
user:/usr/bin$ git

(在没有./的情况下运行)

121981 次浏览

因为在Unix上,当前目录通常不在$PATH中。

当你输入一个命令时,shell会根据PATH变量来查找目录列表。当前目录不在该列表中。

当前目录不在该列表上的原因是出于安全考虑。

假设你是根用户,进入另一个用户的目录,输入sl而不是ls。如果当前目录在PATH中,shell将尝试在该目录中执行sl程序(因为没有其他sl程序)。sl程序可能是恶意的。

它与./一起工作,因为POSIX指定包含/的命令名将直接用作文件名,抑制在$PATH中的搜索。你可以使用完全路径来达到完全相同的效果,但是./更短,更容易编写。

编辑

sl部分只是一个例子。PATH中的目录将按顺序搜索,当匹配成功时执行该程序。因此,根据PATH的外观,键入一个普通命令可能不足以在当前目录中运行程序。

当shell查找$PATH环境变量以查找您的脚本时,将无法在主目录中找到您的脚本。

./表示“在当前目录中查找我的脚本,而不是在$PATH中指定的所有目录中查找”。

当脚本不在路径中时,需要这样做。更多信息请阅读http://www.tldp.org/LDP/Bash-Beginners-Guide/html/sect_02_01.html

当你包含'。’你实际上是给了可执行bash脚本“完整路径”,所以你的shell不需要检查你的path变量。没有'。'你的shell将在你的PATH变量中查找(你可以通过运行echo $PATH来查看你输入的命令是否存在于PATH上的任何文件夹中。如果没有(就像manage.py的情况一样),它表示无法找到该文件。在PATH中包含当前目录被认为是不好的做法,在这里解释得很好:http://www.faqs.org/faqs/unix-faq/faq/part2/section-13.html

在*nix上,与Windows不同,当前目录通常不在$PATH变量中。因此,在执行命令时不搜索当前目录。你不需要./来运行应用程序,因为这些应用程序在你的$PATH中;它们很可能在/bin/usr/bin中。

当bash解释命令行时,它在环境变量$PATH中描述的位置中查找命令。要查看它键入:

echo $PATH

你会有一些用冒号分隔的路径。正如你将看到的,当前路径.通常不在$PATH中。因此,如果您的命令在当前目录中,Bash就无法找到它。你可以通过以下方式更改:

PATH=$PATH:.

这一行添加了$PATH中的当前目录,所以你可以这样做:

manage.py syncdb

建议使用,因为它有安全问题,另外你可能会有奇怪的行为,因为.会根据你所在的目录而变化:)

避免:

PATH=.:$PATH

因为你可以“屏蔽”一些标准命令,并打开安全漏洞的大门:)

这只是我的个人意见。

这个问题已经有了一些很棒的答案,但我想补充一点,如果你的可执行文件在PATH上,当你运行时,你会得到非常不同的输出

./executable

和你逃跑后得到的那些人

executable

(假设您遇到了一个错误消息,而不是另一个),那么问题可能是您的机器上有两个不同版本的可执行文件:一个在路径上,另一个不在路径上。

通过运行

这可执行

而且

whereis executable

它解决了我的问题……我有三个版本的可执行文件,其中只有一个是针对环境正确编译的。

所有这些都有很好的答案,是的,这只适用于在当前目录上运行时,除非你包含绝对路径。请参阅下面的示例。

此外,当我在子文件夹tmp2 (/tmp/tmp2)上有命令时,(点-斜杠)对我来说是有意义的,它使用(双点-斜杠)。

示例:

[fifiip-172-31-17-12 tmp]$ ./StackO.sh


Hello Stack Overflow


[fifi@ip-172-31-17-12 tmp]$ /tmp/StackO.sh


Hello Stack Overflow


[fifi@ip-172-31-17-12 tmp]$ mkdir tmp2


[fifi@ip-172-31-17-12 tmp]$ cd tmp2/


[fifi@ip-172-31-17-12 tmp2]$ ../StackO.sh


Hello Stack Overflow

/ POSIX PATH规则的基本原理

该规则在:为什么在可执行文件或脚本名称之前需要。/(点-斜杠)才能在bash中运行它?中提到,但我想更详细地解释为什么我认为这是一个很好的设计。

首先,该规则的明确完整版本是:

  • 如果路径包含/(例如./someprog/bin/someprog./bin/someprog):使用CWD而不使用path
  • 如果路径不包含/(例如someprog):使用path而不使用CWD

现在,假设运行:

someprog

将搜索:

  • 首先相对于CWD
  • 之后相对于PATH

然后,如果你想从你的发行版运行/bin/someprog,并且你做了:

someprog

它有时会工作,但有时会失败,因为你可能在一个目录中包含另一个不相关的someprog程序。

因此,您很快就会发现这是不可靠的,当您想要使用PATH时,您最终将总是使用绝对路径,因此违背了PATH的目的。

这也是为什么在PATH中使用相对路径是一个非常糟糕的主意。我看着你,node_modules/bin

相反,假设运行:

./someprog

将搜索:

  • 相对于PATH优先
  • 相对于CWD后

然后,如果你只是从git存储库下载了一个脚本someprog,并希望从CWD运行它,你永远不会确定这是实际运行的程序,因为可能你的发行版有一个:

/bin/someprog

这是在你的PATH中,来自去年圣诞节后你喝多了之后安装的某个软件包。

因此,再一次,你将被迫总是运行本地脚本相对于CWD的完整路径,以知道你在运行什么:

"$(pwd)/someprog"

这也会非常烦人。

你可能会想到的另一个规则是:

相对路径只使用PATH,绝对路径只使用CWD

但这再次迫使用户在"$(pwd)/someprog"中对非path脚本总是使用绝对路径。

/路径搜索规则为about问题提供了一个简单的解决方案:

  • 斜杠:不要使用PATH
  • 没有斜杠:只使用PATH

因为当前目录下的文件可以用./somefilesomefile表示,所以它赋予了其中一个特殊的含义,所以它非常容易知道你在运行什么。

有时,你不能相对于PATH搜索some/prog有点烦人,但我没有看到一个更合理的解决方案。