问题描述
在使用Ubuntu终端执行C程序a.out
时,为什么我总是需要在a.out
之前键入./
,而不是只写a.out
?有解决方案吗?
最佳解决办法
当你输入一个程序的名字,例如a.out
时,系统会在PATH中查找这个文件。在我的系统上,PATH被设置为
/usr/lib/lightdm/lightdm:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games
你的可能类似。要检查,请在终端中输入echo $PATH
。
系统按照给定的顺序查看这些目录,如果找不到该程序,则会产生command not found
错误。
在./
前加上命令有效地说:“忘记PATH,我希望你只看当前目录”。
同样,您可以通过在相对或绝对路径前添加命令来告诉系统只查看另一个特定位置,例如:
../
表示在父目录中,例如../hello
在父目录中寻找hello。
./Debug/hello
:“在当前目录的Debug子目录中查找hello
。”
或/bin/ls
:“在目录/bin
中查找ls
”
默认情况下,当前目录不在路径中,因为它被视为安全风险。请参阅超级用户上的Why is . not in the path by default?以了解原因。
可以将当前目录添加到PATH中,但出于链接问题中给出的原因,我不会推荐它。
次佳解决办法
这样做的原因是简单的。
假设您有一个与当前目录中的应用程序具有相同名称的命令。然后在shell中运行命令将调用您的应用程序而不是内置命令。如果没有其他的话,这将是一个安全问题。
通过要求在前面使用./
,shell知道您要使用给定名称执行应用程序,而不是使用该名称的内置命令。
第三种解决办法
./
执行不在$PATH
中的文件,而是执行当前目录中的文件(或通过./home/stefano/script.sh
执行另一个文件)。现在,PATH是一个环境变量,其中包含bash可以查找可执行程序的所有位置,而不具有完整(绝对)路径。
这需要分离以避免运行错误的文件。即如果您的主目录中有一个名为ls
的文件,则它不在您的PATH中,这将防止bash将其与真实的ls
混淆。 PATH变量还定义了搜索顺序:
-
当你运行一个命令,或者一个程序试图创建一个
exec
系统调用(内核的一个特殊方法,程序是如何启动的)时,系统通过浏览PATH中的每个目录来查找文件。一旦找到该程序,即使它位于多个目录中,搜索也会中断,并找到第一个被运行的程序。
要运行文件,您需要在权限中设置可执行位:
-
既然你已经在命令行上,你可以键入
chmod +x finename
。 -
或者,您可以通过右键单击该文件并选择“属性”来设置权限:
您现在可以将该文件复制到PATH中的任何目录,以查看哪些目录在那里 – 并且它们设置在per-user基础上 – 类型echo $PATH
。
stefano@3000-G530:~$ echo $PATH
/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games
如果您创建可执行文件cat
,并将其移至/usr/local/sbin
,则会运行该文件,而不是运行在/bin
中的适当cat
。您可以通过使用type cat
和whereis cat
找到您的文件的位置。
第四种办法
为什么在执行程序之前需要输入./
?
在终端中,只要您输入的应用程序的名称,让我们说gedit
,终端会去看看在包含应用程序(应用程序的二进制文件)的一些(pre-defined)目录。这些目录的名称包含在名为PATH
的变量中。您可以通过执行echo $PATH
来查看该变量中的内容。看到由:
分隔的那些目录?这些是终端将搜索的目录,如果您只键入gedit
,nautilus
或a.out
。正如你所看到的,你的a.out
程序的路径不存在。当你这样做./a.out
,你告诉终端“看在当前目录下,并运行a.out
,不要去看看在PATH
。
解决方案1
如果您不想每次输入./
,则需要在$PATH
中添加a.out
的目录。在下面的说明中,我将假定a.out
的路径是/path/to/programs/
,但您应该将其更改为您的实际路径。
-
只需将以下行添加到文件
~/.pam_environment
的末尾:PATH DEFAULT=${PATH}:/path/to/programs
-
注销并重新登录。现在,您可以从任何目录运行不带
./
的a.out
。
如果其他目录中有其他程序,可以将它们添加到上面的行中。不过,我建议有一个名为”myPrograms”的目录,并将所有程序放在它下面。
解决方案2
Note: change
userName
to your actual Ubuntu username.
如果你想要运行其他程序呢?他们都在不同的文件夹?那么,”more organized”解决方案就是在您的主目录下创建一个名为bin
的文件夹,然后在该文件夹下添加符号链接(快捷方式)。就是这样:
-
mkdir /home/userName/bin
-
这将在您的主目录下创建文件夹
bin
。
-
-
ln -s /path/to/programs/a.out /home/userName/bin
-
这将在
bin
下创建a.out
程序的”symbolic link”(基本上是一个快捷方式)。
-
-
注销并重新登录。现在,您可以从任何目录运行不带
./
的a.out
。
现在,无论何时您在其他地方都有其他程序,让我们说您桌面上的程序b.in
,您只需要:ln -s /home/userName/Desktop/b.in /home/userName/bin
,然后您就可以在没有./
的情况下运行它。
Note: thanks to @Joe’s comment, when you do backups, symbolic links have to be handled specially. By default,
rsync
doesn’t process them at all, so when you restore, they’re not there.