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


288

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

$ ./manage.py syncdb

如果不这样做,则会收到错误消息:

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

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

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

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

(不带./


4
这是迄今为止我遇到的最好的文档:linfo.org/dot_slash.html
odigity

Answers:


305

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

当您键入命令时,外壳程序将查找该PATH变量指定的目录列表。当前目录不在该列表中。

该列表中没有当前目录的原因是安全性。

假设您是root用户,然后进入另一个用户的目录并键入sl而不是ls。如果当前目录位于中PATH,则Shell将尝试执行该sl目录中的程序(因为没有其他sl程序)。该sl程序可能是恶意的。

./之所以可以使用它,是因为POSIX指定包含a的命令名称/将直接用作文件名,从而禁止在中搜索$PATH。您可以使用完整路径来获得完全相同的效果,但是./它更短且更容易编写。

编辑

sl部分只是一个例子。PATH依次搜索其中的目录,并在匹配时执行该程序。因此,根据PATH外观,键入常规命令可能不足以在当前目录中运行该程序。


47
您无需输错任何内容。用户可能刚刚下载了其中包含ls可执行文件的恶意软件包。
朱利诺

13
只是给所有人的便条,说这仅在Unix而非Windows中,在Powershell中是相同的-您必须.\my.bat执行其他操作才能执行
manojlds 2011年

1
@gaearon ergh,我说“不是别名”,当时应该是“严格来说是别名”。
Charles Duffy

4
这是一个非常有用的解释。20多年前,当我稍微使用DOS时,我认为CMD会检查当前目录,然后是PATH,因此Linux的行为不是我所期望的,但是这很有意义。
TecBrat 2013年

2
@cnicutar:今天有趣的是,我发现有一个sl称为蒸汽机车的命令,尽管默认情况下不可用;-)
blackSmith 2014年

51

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

echo $PATH

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

PATH=$PATH:.

此行将当前目录添加到其中,$PATH因此您可以执行以下操作:

manage.py syncdb

这是推荐,因为它有安全问题,再加上你可以有奇怪的行为,因为.当你在目录因人而异:)

避免:

PATH=.:$PATH

正如您可以“掩盖”一些标准命令并打开安全漏洞的大门:)

只是我的两分钱。


42

当外壳程序查看$PATH环境变量以查找脚本时,找不到位于主目录中的脚本。

./说“在当前目录下找我的剧本,而不是看着都在指定的目录$PATH”。


5

当您包含“。”时 您实质上是为可执行的bash脚本提供“完整路径”,因此您的shell不需要检查PATH变量。不带“。” 您的外壳将在您的PATH变量中查找(可以通过运行echo $PATH以查看键入的命令是否位于PATH上的任何文件夹中来查看。如果不存在(与manage.py相同),它会说找不到文件。将当前目录包含在PATH中是不正确的做法,在此处对此进行了很好的解释:http : //www.faqs.org/faqs/unix-faq/faq/part2/section- 13.html


2

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


1

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

./executable

跑到你得到的那些

executable

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

通过运行检查

哪个可执行文件

whereis executable

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


0

理由为/POSIX路径规则

在以下位置提到了该规则:为什么在可执行文件或脚本名称之前需要./(点斜杠)才能在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

然后,如果您只是someprog从git存储库下载了一个脚本并想从CWD运行它,则您将无法确定这是将要运行的实际程序,因为您的发行版可能具有:

/bin/someprog

去年圣诞节后喝了太多酒后安装的某些软件包中的PATH包含在PATH中。

因此,再次,您将不得不始终使用完整路径相对于CWD运行本地脚本,以了解您正在运行的内容:

"$(pwd)/someprog"

这也将非常烦人。

您可能会想出的另一条规则是:

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

但这又迫使用户始终对的非PATH脚本使用绝对路径"$(pwd)/someprog"

/路径搜索规则提供了一个简单的记忆解决问题有关:

  • 斜线:不要使用 PATH
  • 不加斜线:仅使用 PATH

通过依靠当前目录中的文件可以表示为./somefile或的事实,使始终知道正在运行的内容变得非常容易somefile,因此它给其中一个赋予了特殊的含义。

有时,您无法搜索some/prog相对于会有点烦人PATH,但我看不出对此有更明智的解决方案。



-2

所有人都对这个问题有很好的答案,是的,这仅适用于在当前目录上运行它的情况,除非您包括绝对路径。请参阅下面的示例。

另外,当我在子文件夹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
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.