字数 1387,阅读大约需 7 分钟
导读:刚接触 Linux 的同学,经常会遇到一个奇怪的现象:当前目录下明明有一个脚本文件 hello.sh,直接输入文件名却报错 command not found。但只要在前面加上 ./,写成 ./hello.sh,就能正常运行。
这个 ./ 到底是什么意思?为什么 Linux 不能直接运行眼前的这个文件?
1. ./ 代表“当前目录”
在 Linux 中,. 和 .. 是特殊的目录符号:
所以,./hello.sh 本质上是一个相对路径,意思是“运行当前目录下的 hello.sh”。
同理,如果你想运行上一级目录中的脚本,就是 ../hello.sh。这只是在给系统指路,并不是什么神秘的脚本语法。
2. 为什么直接输入文件名找不到?(环境变量 PATH)
当你在终端输入一个命令(比如 ls)时,系统并不会在当前文件夹里翻箱倒柜,而是去一组提前定义好的目录中寻找同名可执行文件。
这组目录存放在环境变量 $PATH 中。我们可以打印出来看看:
$ echo $PATH
/usr/local/bin:/usr/bin:/bin:/home/fly/miniconda3/bin
(多个目录用冒号 : 隔开)
当你输入 ls 时,系统会依次去 /usr/local/bin、/usr/bin 等目录里找,最终在 /usr/bin/ls 找到了它并运行。
但是,当前目录 . 默认是不在 $PATH 中的。所以,哪怕 hello.sh 就在你眼前,如果不加路径,系统依然会冷酷地抛出 command not found。
3. 加上 ./ 之后发生了什么?
一旦你在输入中加入了 /(斜杠),系统就明白你提供的是一个具体路径,而不再是一个纯命令。此时,它会直接去该路径下找文件,不再理会 $PATH。
- • 直接输
hello.sh:系统认为这是一个内置命令或全局可执行文件,会去 $PATH 包含的目录里搜索。 - • 输入
./hello.sh:系统明白这是路径,直接去当前目录下定位并执行该文件。
同理,使用绝对路径 /home/fly/scripts/hello.sh 也是一样的道理。
4. 为什么 Linux 不默认把当前目录加进 PATH?
Windows 默认会搜索当前目录,为什么 Linux 不这么做?答案是:安全安全,还是安全。
试想一下:你从网上下载了一个压缩包并解压,里面潜伏着一个恶意程序,名字也叫 ls。
如果你切进这个目录,习惯性地输入 ls 想查看文件,如果 Linux 默认搜索当前目录,系统就会优先运行这个恶意的 ls,而不是系统自带的 /usr/bin/ls。这会让黑客非常轻易地拿到系统的控制权。
因此,Linux 强制要求:想运行当前目录的文件,必须显式地加上 ./。这相当于一个确认步骤:“我非常清楚我在干什么,我就是要运行当前目录下这个特定的文件。”
5. 常见坑点:加了 ./ 依然报错 Permission denied?
刚写好的脚本,即使加了 ./,运行后也经常会遇到:
$ ./hello.sh
bash: ./hello.sh: Permission denied
这是因为在 Linux 中,新创建的文件默认是没有执行权限(Executable)的。
我们可以用 ls -l 确认一下:
$ ls -l hello.sh
-rw-r--r-- 1 fly fly 100 Jul 13 20:00 hello.sh
看到前面的 -rw-r--r-- 了吗?里面只有 r(读)和 w(写),没有 x(执行)。
解决办法很简单,给它赋予执行权限:
$ chmod +x hello.sh
此时再次 ls -l,权限就会变成 -rwxr-xr-x(文件名可能还会变成绿色),然后再运行 ./hello.sh 就没问题了。
6. 避坑指南:Shebang(第一行的神秘符号)
为了让 ./hello.sh 能正确运行,脚本的第一行通常需要写上:
#!/usr/bin/env bash
或者 Python 脚本写:
#!/usr/bin/env python3
这行代码叫 Shebang(由井号 # 和感叹号 ! 组成),作用是告诉系统:“请用下面指定的解释器来跑我这个文件。”
💡 一个小技巧:不用 ./ 也能跑脚本的方法
如果你的脚本没有执行权限,或者你不想写 ./,也可以直接把脚本作为参数传给解释器:
$ bash hello.sh
$ python3 hello.py
这种情况下,系统真正运行的是全局命令 bash 或 python3(它们在 $PATH 里,不需要路径),而你的脚本只是作为一个普通文本数据塞给它们。所以这种方式不需要 ./,也不需要脚本具有执行权限。
7. 怎样才能像 ls 一样,直接输入脚本名就能运行?
如果你写了一个非常常用的脚本,每次都敲 ./ 确实有点烦。想实现“全局直接调用”,有两种常用办法:
- 1. 把脚本放到系统已有的 PATH 目录中(例如
/usr/local/bin 或 ~/.local/bin)。 - 2. 把脚本所在的文件夹路径,加到
$PATH 环境变量中(通过修改 ~/.bashrc 或 ~/.zshrc)。
不过,对于日常临时写的、只在当前目录下用一次的脚本,使用 ./script.sh 依然是最安全、最方便的选择。
💡 总结
- •
./ 代表当前目录,它的本质是给系统指引相对路径。 - • 系统默认不搜索当前目录(出于安全考虑),所以必须显式指定
./ 才能执行当前目录下的程序。 - 1. 检查是否赋予了执行权限(用
chmod +x)。 - 2. 检查脚本第一行是否写了正确的 Shebang(如
#!/usr/bin/env bash)。