文件扩展名以及与 Linux 中程序的关联

文件扩展名以及与 Linux 中程序的关联

在 Windows 中,我们可以将文件的扩展名与程序关联起来。例如,由于扩展名
,文件test.pl可以由安装的解释器运行。 在 Linux 中,它需要作为第一行。 这是因为Linux中的文件扩展名和程序之间没有关联吗?Perlpl
#!/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 不依赖于文件的后缀。许多程序既不需要也不会自动添加其典型的后缀,一个例外是压缩程序(例如gzipbzip2),它通常用压缩文件替换原始文件,添加后缀来标记压缩类型(这些是少数几个可以使用压缩文件的程序之一)抱怨后缀不正确)。

相反,该文件是通过一系列测试通过其内容来识别的,寻找“幻数”和其他标识符(您可以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 扩展名,并且它们始终是可执行文件,即使没有任何扩展名。

相关内容