在 Windows 中,我们可以将文件的扩展名与程序关联起来。例如,由于扩展名
,文件test.pl
可以由安装的解释器运行。 在 Linux 中,它需要作为第一行。 这是因为Linux中的文件扩展名和程序之间没有关联吗?Perl
pl
#!/usr/bin/perl
答案1
不,不是这个意思。如果您有一个设置了执行权限的文本文件(例如chmod a+x somefile
),并且文件的第一行类似于
"#!/path/to/executable"
它只是告诉 Unix 使用什么程序来执行脚本。如果一个文本文件被标记为可执行文件(即脚本),Unix 将启动以此方式指定的任何程序,并将文本文件的其余部分(脚本)发送到该程序。通常,指定的程序是 shell(/bin/sh
、/bin/csh
或/bin/bash
)、某些编程语言(Perl、Python 或 Ruby)的解释器或执行脚本的其他程序(如文本操纵器 Awk 或 Sed)。
通常,“#”在许多语言中指定注释,仅当第一的该行以“#!”开头这是很特别的。如果一个文件被标记为可执行文件但不以“#!”开头,Unix 将假定它是某种二进制文件(例如,由 C 编译器和链接器生成的 ELF 可执行文件)。
一般来说,Unix 不依赖于文件的后缀。许多程序既不需要也不会自动添加其典型的后缀,一个例外是压缩程序(例如gzip
和bzip2
),它通常用压缩文件替换原始文件,添加后缀来标记压缩类型(这些是少数几个可以使用压缩文件的程序之一)抱怨后缀不正确)。
相反,该文件是通过一系列测试通过其内容来识别的,寻找“幻数”和其他标识符(您可以file
在某些文件上尝试该命令来测试这一点)。 GNOME 和 KDE 下的文件浏览器也使用它来选择图标和程序列表来打开/编辑文件。这里,文件的 MIME 类型通过此类测试来识别,然后从与 MIME 类型关联的列表中找到用于查看和编辑的合适程序 - 而不是 Windows 中的后缀。
因为其中一个测试是检查文本文件的第一行是否是“#!/something”,然后查看“something”是什么;例如,您可以说将#!/usr/bin/perl
文件标识为 perl 脚本 - 但这更多的是副作用。即使文件不以“#!”开头,测试也应该能够正确识别该文件。无论如何,用于识别它的是文件的内容,而不是任意后缀。因此,像 .pl (Perl) 和 .awk (Awk) 这样的结尾纯粹是为了帮助人类用户识别文件的类型,Unix 不会使用它来限制类型(如 Windows 中的后缀)。
实际上,您可以创建一个没有“#!/something”的“脚本”,但 Unix 无法自动将其作为可执行文件运行(它不知道在哪个程序中运行该脚本)。相反,您必须使用类似perl myscript
或 的内容“手动”启动它python myscript
。大型 Python 和 Perl 应用程序中的许多脚本实际上不会以“#!/something”开头,因为它们是“内部使用”的脚本,不打算由用户直接调用。
相反,您将启动主脚本(它以“#!/something”开头),然后在该脚本运行时将这些其他脚本传递给解释器。
答案2
在 Windows 中,我们可以将文件的扩展名与程序关联起来。例如,由于 pl 扩展名,文件 test.pl 可以由已安装的 Perl 解释器运行。
是的,但扩展名只是关于文件类型的提示。 Perl 语法脚本仍然是 Perl 语法脚本,无论它是否被称为“.pl”、“.exe”或“.doc”。例如,您仍然可以通过直接调用解释器来执行它;perl.exe thisfile.doc
如果文件是 perl 语法文件,则可以使用。如果您愿意,也可以将“.blah”与 Perl 文件关联起来。
在 Linux 中,它需要 #!/usr/bin/perl 作为第一行。
再次强调,这只是一个提示。您仍然可以通过直接调用脚本作为命令的参数来调用不带 shebang 的 perl 文件perl
。
这是因为Linux中的文件扩展名和程序之间没有关联吗
从技术上讲,是的。
Linux 实际上有多种方法来识别可执行格式。该file
命令提供了对此的说明。它包含一个“魔法”数据库(在特定偏移处具有特定长度的字符串),用于确定某文件的类型。它通过检查文件的内容来确定它是什么来做到这一点。另一种方法是使用文件扩展名。您实际上可以使用名为“binfmt_misc”的系统来注册您想要的行为。维基百科解释了它是如何工作的(使用“魔法”和文件扩展名)。
在 Linux 中,通过文件权限上“可执行”位的概念,文件被任意视为“可执行”。当您尝试运行具有可执行位的应用程序时,内核将读取文件的前几个字节以确定要执行的操作。
- 如果文件以以下开头,
#!
则调用提供的路径中的命令,并将以下文件作为该命令的最后一个参数。 - 如果文件以 ELF 开头,则运行
/lib{64}/ld-linux.so
(这实际上是从 ELF 二进制文件的节头中获取的,它不是刚刚使用的静态路径),然后运行命令(这会执行一系列库的静态加载)。 - 查看适用于 binfmt_misc 的规则。
a.out 格式我不太熟悉它们的调用——我假设 ld-linux.so 加载器仍然可以处理它们。
答案3
不,这不对。 Shebang ( #!
) 以及文件类型和应用程序之间的关联有不同的用途,您可以在桌面 Linux 发行版中找到这两者。
习惯上,在从命令行或其他脚本调用的可执行脚本中使用前者,并且它不依赖于文件扩展名。在 Windows 中,通过 PATHEXT 环境变量可以获得类似的功能,它依赖于文件扩展名。
后者为点击桌面界面上的图标或文件名的用户提供服务。在Linux世界中,这来自将 MIME 类型与应用程序关联当然,这是由特定工具处理的,不需要阅读典型桌面用户的规范。
答案4
你只是不能做这样的比较,并不是说 GNU/Linux 没有文件扩展名和程序之间的关联,而是因为 GNU/Linux 实际上并不关心它。
您拥有文件权限,并且如果您的文件是可执行的,它将始终在任何脚本的第一行搜索 shebang 以查看如何执行它。
另一方面,Linux 的 ELF 二进制文件不像 Windows 二进制文件那样具有 exe 扩展名,并且它们始终是可执行文件,即使没有任何扩展名。