文件扩展名是否有任何用途(对于操作系统)?

miz*_*ech 83 files file-format mime-type

Linux 通过文件头中的代码确定文件的类型。它不依赖于文件扩展名来了解用于打开文件的软件。

这就是我从我的教育中记得的。如果我错了,请纠正我!

最近在 Ubuntu 系统上工作了一下:我在系统上看到很多文件都有像.sh, .txt, .o,等扩展名.c

现在我想知道:这些扩展是否仅适用于人类?所以人们应该知道它是什么类型的文件?

或者它们对操作系统也有某种用途吗?

Byt*_*der 75

这里没有 100% 非黑即白的答案。

通常Linux 不依赖文件名(和文件扩展名,即通常最后一个句点之后的文件名部分),而是通过检查其内容的前几个字节并将其与已知幻数列表进行比较来确定文件类型.

例如,所有位图图像文件(通常带有扩展名.bmp)必须以前BM两个字节中的字母开头。大多数脚本语言(如 Bash、Python、Perl、AWK 等)中的脚本(基本上所有#以注释开头的行)都可能包含像#!/bin/bash第一行这样的 shebang 。这个特殊的注释告诉系统用哪个应用程序打开文件。

所以通常操作系统依赖文件内容而不是文件名来确定文件类型,但声明在 Linux 上从不需要文件扩展名只是事实的一半。


应用程序当然可以按照自己的意愿执行文件检查,包括验证文件名和扩展名。一个例子是 Gnome 之眼(eog标准图片查看器),它通过文件扩展名确定图像格式,如果与内容不匹配,则会引发错误。可以讨论这是错误还是功能...

然而,即使是操作系统的某些部分也依赖于文件扩展名,例如在解析您的软件源文件时/etc/apt/sources.list.d/- 只有具有*.list扩展名的文件被解析,所有其他文件都被忽略。它可能不是在这里主要用于确定文件类型,而是用于启用/禁用某些文件的解析,但它仍然是影响系统如何处理文件的文件扩展名。

当然还有最从文件扩展名的人类用户利润,使明显的一个文件的类型,也可以用相同的基本名称的多个文件和不同的扩展名如site.htmlsite.phpsite.jssite.css等缺点当然是文件扩展名,实际文件类型/内容不一定要匹配。

此外,跨平台互操作性也需要它,例如 Windows 不知道如何处理readme文件,而只知道readme.txt.

  • 我挑战的句子是这样的:“Linux ...通过检查前几个字节来确定文件类型”。你在这句话中使用的“Linux”的定义是什么?`file` 实用程序的存在并不能真正证明任何事情;这是一个有用的工具,可以存在于任何操作系统上。操作系统的哪个基本部分使运行 `file` 比通配文件名更“正确”? (2认同)

Rin*_*ind 47

Linux 通过文件头中的代码确定文件的类型。它不依赖于文件扩展名来知道软件用于打开文件。

这就是我从我的教育中记得的。如果我错了,请纠正我!

  • 没记错。

这些扩展是否仅适用于人类?

  • 是的,但是。

当您与其他依赖于扩展的操作系统交互时,使用它们是更明智的想法。

在 Windows 中,打开软件附加到扩展。

打开一个名为文本文件“文件”是很难在Windows不是打开一个名为“file.txt的”(你将需要从切换打开文件对话框相同的文件*.txt,以*.*每次)。TAB 和分号分隔的文本文件也是如此。导入和导出电子邮件(.mbox 扩展名)也是如此。

尤其是当您编写软件时。与“software.html”和“software.js”相比,打开名为“software1”的HTML文件和名为“software2”的JavaScript文件变得更加困难。


如果 Linux 中存在一个文件扩展名很重要的系统,我会称其为错误。当软件依赖于文件扩展名时,这是可利用的。我们使用解释器指令来识别文件是什么(“文件的前两个字节可以是字符“#!”,它们构成一个幻数(十六进制23和21,“#”和“!”的ASCII值)。 ") 通常被称为shebang,")。

最著名的文件扩展问题是Windows 上的LOVE-LETTER-FOR-YOU.TXT.vbs。这是在文件资源管理器中显示为文本文件的可视化基本脚本。

在 Ubuntu 中,当您从 Nautilus 启动文件时,您会收到它将要执行的操作的警告。从 Nautilus 执行脚本,它想要启动一些应该打开 gEdit 的软件,这显然是一个问题,我们会收到有关它的警告。

在命令行中执行某些操作时,您可以直观地看到扩展名是什么。如果它以 .vbs 结尾,我会开始怀疑(不是 .vbs 在 Linux 上是可执行的。至少不是没有更多的努力;))。

  • 我完全不明白你最后一句话想说什么。首先,这是隐藏扩展名而不是拥有扩展名的问题,其次,漏洞利用在 Linux 中的工作方式相同 - 您命名一个二进制文件 `readme.txt` 并使其可执行。如果用户执行它,它不会打开编辑器,而是运行代码。在这方面,让扩展变得重要(但不隐藏它们)对于不精通的用户来说更安全且更容易解释。还有其他区别(最明显的是不从当前目录执行文件),但它们与扩展无关。 (34认同)
  • 这是一个非常错误的答案。Linux 的某些部分使用幻数来确定文件类型。在命令行执行文件。但是系统的其他重要部分使用文件扩展名来了解要查看的内容,无论是动态链接器(需要 .so 文件)、modprobe、构建系统、插件、python 库、ruby 等。许多文件都没有没有幻数,`file` 是基于启发式的,不是确定的。 (20认同)
  • linux:由于 make 是围绕依赖于文件扩展名的规则构建的,所以这不会使(不是双关语)扩展名不仅仅适用于人类吗? (9认同)
  • @techraf 实际上,*文件管理器* 可能会尝试使用文本编辑器打开 `readme.txt` 文件。我刚刚尝试在 KDE 中使用 dolphin,创建一个添加可执行权限的 shell 脚本,将其保存为 `.txt` 并单击它会使其在 Kate 中打开。如果我将它重命名为 `.sh` 然后点击它运行它。 (5认同)
  • “Linux 通过文件头中的代码确定文件的类型”“正确的”WTF?什么“文件头中的代码”?没有这样的代码,Linux 中也没有这样一个通用的“文件头”。 (4认同)
  • 正如其他人指出的那样,某些文件类型很难通过其内容来定义,例如基于 zip 存档(JAR、ODF、OOXML 等)的许多格式。文件也可能包含在两种情况下都有效的数据(例如,您可以连接 zip 存档和 GIF,并且文件在两种格式下都有效)。因此,允许用户以命名约定的形式提供额外信息可以改善用户体验。在“ILOVEYOU”上调用“file”并决定无论如何都应该通过易受攻击的解释器运行它不再安全 - 攻击者确定名称和内容。 (3认同)
  • 另外,“在 Linux 中,当您从 Nautilus 启动文件时...”应该真正阅读为“在 Nautilus 中,当您启动文件时...”,或者“...双击文件...”。它与作为内核或整个操作系统的 Linux 完全无关,而只是该特定应用程序做出的 UI 决定。Nautilus 的 Windows 端口可以做出完全相同的决定。 (3认同)
  • @IMSoP 不仅“非常难”,而且有时是不可能的。如果`file` 不知道如何识别一种更奇特的文件格式,你最好希望它有一个可以搜索的扩展名,否则祝你使用该文件好运。 (3认同)
  • Linux 发行版也需要扩展来确定文件类型,他们确实使用它,试试这个:`cp /bin/ls ~/readme.txt` 然后启动 nautilus 并打开这个新文件,它将在文本编辑器中打开。尝试编译一个没有 `.c` 扩展名的 C 程序代码你会得到错误,你仍然认为 gcc 有错误吗? (3认同)
  • 我会根据扩展调用一个错误。应该做的是(是的,我知道这会花费更多的处理器时间)是应该调用并检查命令“文件”以检查幻数。@techraf“如果用户执行它,它不会打开编辑器,而是运行代码”是用户问题,而不是系统安全问题。当我们看到 README.TXT 时,我们使用“more”、“gedit”、“vim”或“nano”来查看它。我们不执行自述文件。这是我们在 Linux 中不需要的 Windows 心态。 (2认同)
  • “如果在 Linux 中有一个系统,文件扩展名很重要,我会称之为错误”——嗯,所以`cc` 的历史实践是一个错误?我相信 C 编译器一直依靠文件扩展名来区分需要传递给 `cc1` 的 `.c` 参数和可以直接传递给 `ld` 的 `.o` 参数。 (2认同)

Zan*_*nna 24

正如其他人提到的,在 Linux 中使用了解释器指令方法(将一些元数据存储在文件中作为标头或幻数,以便正确的解释器可以被告知读取它)而不是 Windows 使用的文件扩展名关联方法。

这意味着您几乎可以使用您喜欢的任何名称创建一个文件……但有一些例外

然而

我想补充一句警告。

如果您的系统上有一些来自使用文件名关联的系统的文件,则这些文件可能没有那些幻数或标题。文件扩展名用于通过能够读取这些文件的应用程序来识别这些文件,如果您重命名这些文件,您可能会遇到一些意想不到的效果。例如:

如果您将文件重命名My Novel.docMy-Novel,Libreoffice 仍然可以打开它,但它会以“无标题”的形式打开,您必须重新命名才能保存它(Libreoffice 默认添加一个扩展名,因此您将拥有两个文件My-NovelMy-Novel.odt,这可能很烦人)

更严重的是,如果你将文件 My Spreadsheet.xlsx 重命名为 My-Spreadsheet,然后尝试打开它,xdg-open My-Spreadsheet你会得到这个(因为它实际上是一个压缩文件):

如果您将文件重命名My Spreadsheet.xlsMy-Spreadsheet,当xdg-open My-Spreadsheet您收到错误提示时

错误打开位置:没有应用程序注册为处理此文件

(尽管在这两种情况下它都可以正常工作soffice My-Spreadsheet

如果您然后将无扩展名文件重命名为My-Spreadsheet.odswithmv并尝试打开它,您将得到以下信息:

(修复失败)

并且您必须重新打开原始扩展名才能正确打开文件(然后您可以根据需要转换格式)

特尔;博士:

如果您有带有扩展名的非本地文件,请不要在一切正常的情况下删除扩展名!

  • @PeterGreen Windows 文件系统也不会对文件类型做任何事情。图形外壳(Windows 资源管理器)使用文件扩展名来选择双击操作,但从技术上讲,这只是一个运行在操作系统之上的程序,就像 Nautilus 一样。完全可以编写具有这种行为的 Linux 文件管理器,或者编写检查文件内容的 Windows 文件管理器。 (5认同)
  • 没有文件扩展名的新型 MS Office 文档(docx、xlsx、pptx 等)在存档管理器中打开,因为这些文件类型实际上只是普通的 ZIP 压缩文件,其中包含定义文档内容所需的所有 XML 文档和媒体文件。ZIP 压缩目录的文件格式现在非常普遍。 (4认同)
  • linux 文件系统对文件类型没有任何作用。这完全取决于在它上面运行的程序。 (3认同)

IMS*_*SoP 24

我想对此采取与其他答案不同的方法,并挑战“Linux”或“Windows”与此有关的概念(请耐心等待)。

文件扩展名的概念可以简单地表述为“根据文件名称的一部分来识别文件类型的约定”。识别文件类型的其他常见约定是将其内容与已知签名的数据库进行比较(“幻数”方法),并将其存储为文件系统上的额外属性(原始 MacOS 中使用的方法) .

由于 Windows 或 Linux 系统上的每个文件都有名称和内容,因此想要知道文件类型的进程可以使用他们认为合适的“扩展名”或“幻数”方法。元数据方法通常不可用,因为在大多数文件系统上没有此属性的标准位置。

在 Windows 上,使用文件扩展名作为识别文件的主要方式有着悠久的传统。最明显的是,当您双击文件以确定要启动哪个应用程序时,图形文件浏览器(Windows 3.1 上的文件管理器和现代 Windows 上的资源管理器)会使用它。在 Linux(以及更普遍的基于 Unix 的系统)上,检查内容有更多的传统;最值得注意的是,内核查看直接执行的文件的开头以确定如何运行它;脚本文件可以通过开头跟#!解释器的路径来指示要使用的解释器。

这些传统影响了为每个系统编写的程序的 UI 设计,但也有很多例外,因为每种方法在不同情况下都有优缺点。使用文件扩展名而不是检查内容的原因包括:

  • 与检查文件名相比,检查文件内容的成本相当高;因此,例如“查找所有名为 *.conf 的文件”将比“查找第一行与此签名匹配的所有文件”快得多
  • 文件内容可能不明确;许多文件格式实际上只是以特殊方式处理的文本文件,许多其他文件格式是特殊结构的 zip 文件,为这些文件定义准确的签名可能很棘手
  • 一个文件可以真正作为多种类型有效;HTML 文件也可能是有效的 XML,连接在一起的 zip 文件和 GIF 对两种格式都有效
  • 幻数匹配可能会导致误报;没有标题的文件格式可能会以字节“GIF89a”开头,并被误认为是 GIF 图像
  • 重命名文件可以方便地将其标记为“已禁用”;例如,将“foo.conf”更改为“foo.conf~”以指示备份比编辑文件以注释掉其所有指令更容易,并且比将其从自动加载的目录中移出更方便;同样,将 .php 文件重命名为 .txt 将告诉 Apache 将其源作为纯文本提供,而不是将其传递给 PHP 引擎

默认情况下使用文件名的 Linux 程序示例(但可能有其他模式):

  • gzip 和 gunzip 对任何以“.gz”结尾的文件有特殊处理
  • gcc 会将 ".c" 文件作为 C 处理,将 ".cc" 或 ".C" 作为 C++ 处理

  • @DocSalvager 很好,这与任何措辞一样笨拙。我对其进行了一些改写,以明确表示shebang 不会*使* 脚本可执行,它只是更改了*如何* 执行。 (2认同)

Dmi*_*yev 16

实际上,有些技术确实依赖于文件扩展名,因此如果您在 Ubuntu 中使用这些技术,您也必须依赖于扩展名。几个例子:

  • gcc使用扩展名来区分 C 和 C++ 文件。如果没有扩展名,几乎不可能区分它们(想象一个没有类的 C++ 文件)。
  • 许多文件 ( docx, jar, apk) 只是特别结构化的 ZIP 档案。虽然您通常可以从内容推断类型,但并不总是可能的(例如,Java 清单在文件中是可选jar)。

在这种情况下不使用文件扩展名只能使用 hacky 解决方法,并且可能非常容易出错。

  • @BenVoigt `make` 也是一个很好的例子,但是 `gcc` 同样严重依赖于文件名。这里有一个比 `.c` 和 `.cc` 更清晰的例子:对于 C,`gcc` 使用后缀来判断它的第一步是预处理(`.c`)、编译(`.i`)、汇编(` .s`) 或链接 (`.o`)。[在这里,我使用`-E`、`-S` 和`-c` 来告诉`gcc` 从哪里*停止*,但它使用文件名来知道从哪里*开始*。](https://paste. ubuntu.com/23857695/) `gcc something.cc` 不会链接到正确的 C++ 库,但它*会*将文件视为 C++,这就是为什么许多用户对他们在制作时收到的错误消息感到困惑错误。 (2认同)

Ser*_*nyy 6

您的第一个假设是正确的:Linux 上的扩展无关紧要,仅对人类有用(以及其他关心扩展的非类 Unix 操作系统)。文件的类型由文件中的前 32 位数据决定,这被称为幻数 这就是为什么 shell 脚本需要#!line - 来告诉操作系统要调用哪个解释器。没有它,shell 脚本只是文本文件。

就文件管理器而言,他们确实想知道某些文件的扩展名,例如.desktopfiles ,它与 Window 版本的快捷方式基本相同,但具有更多功能。但就操作系统而言,它需要知道文件中的内容,而不是其名称中的内容

  • *在大多数情况下*他们没有,不。然而,你的第一句话声称它们从未被使用过,只对人类重要。这并不完全正确。`gunzip` 是一个例子,`eog` 是另一个例子。此外,如果没有正确的扩展名,许多工具不会自动完成名称。我要说的是,它比“扩展总是无关紧要的”要复杂一些。 (8认同)
  • 这并不完全正确。有些程序需要特定的扩展名。最常用的例子可能是`gunzip`,如果文件不是`foo.gz`,它就不会解压缩文件。 (4认同)
  • @Serg 当然,您可以狭义地定义操作系统,并获得对该问题的简单回答。不过,这并不是一个特别有用的答案,因为用户使用计算机所做的绝大多数事情都涉及您排除的软件。请注意,该问题将“仅适用于人类”与“操作系统”进行了对比;我不认为他们的意思是“内核”。 (2认同)
  • @Serg“*显然操作系统不是一个很有争议的话题*”嗯,需要引用。Canonical [将 Ubuntu 称为“操作系统”。](https://www.ubuntu.com/about/about-ubuntu) 你说操作系统是“由内核和几个基本服务组成的”,但你没有说明您认为这些是哪些“基本服务”。我特别想知道您认为 systemd 的哪些部分是操作系统组件,哪些不是。这个答案隐含地使用了一个模糊的“操作系统”概念,而不是大多数人对该术语的意思,尤其是在 *nix 圈子中。 (2认同)

cot*_*eyr 5

这对于评论答案来说太大了。

请记住,即使“扩展名”也有很多不同的含义。

你所说的似乎是 . 后的 3 个字母。DOS 使 8.3 格式真正流行起来,直到今天 Windows 还在使用 .3 部分。

Linux 有很多文件,如 .conf 或 .list 或 .d 或 .c ,它们具有意义,但并不是 8.3 意义上的真正扩展。例如,Apache 在 /etc/apache2/sites-enabled/website.conf 中查看其配置指令。虽然系统使用 MIME 类型和内容标头以及什么不能确定它是文本文件,但 Apache(默认情况下)仍然不会加载它而不以 .conf 结尾。

.c 是另一个伟大的。是的,它是一个文本文件,但 gcc 依赖于 main.c 成为 main.o 并最终成为 main(链接后)。系统在任何时候都不会使用 .c、.o 或没有扩展名来表示内容的任何意义,而是 .c 之后的内容。确实有一定的意义。您可能会将 SCM 设置为忽略 main.o 和 main。

要点是这样的:扩展不像在 Windows 中那样使用。内核不会执行 .txt 文件,因为您删除了名称的 .txt 部分。如果设置了执行权限,执行 .txt 文件也很高兴。话虽如此,它们确实有意义,并且仍然在“计算机级别”上用于许多事情。

  • Windows 也不再受`x.3` 命名方案的约束,你有更长的扩展名以及`.doxc`、`.torrent`、`.part` 等。它只是许多文件格式和扩展已经在 8.3 命名仍然存在的时候定义了,后来的格式大多只是简单地适应了使用最多 3 个字母的约定。 (2认同)
  • @coteyr 同样,这完全取决于我们所说的“操作系统”是什么意思。*文件管理器*肯定会查找“AME”的注册表项,并告诉我“foo.txt”是一个文本文件。但是在命令提示符下运行 `dir` 不会告诉我这样的事情;它根本不会在意。在两个操作系统上执行文件当然是一个例外;如果问题仅限于这些,答案将是 DOS/Windows *只*关心名称,而 Unix/Linux *只*关心文件的执行权限和第一个字节。除此之外,总会有一些应用程序选择要遵循的约定。 (2认同)
  • @coteyr 您忘记了 Windows 3.1 及更高版本中的 \*.scr (屏幕保护程序二进制文件)。也就是说,即使在 DOS/Windows 系统中,即使是可执行文件的文件扩展名*仍然*只是一种方便。具体细节在很大程度上取决于您绘制“操作系统”线的位置,但您始终可以将二进制文件加载到内存中并自己跳入其中,完成通常要求操作系统执行的工作。在 MS-DOS 中,如果您查看 command.com,我很确定有一个像 EXE COM 这样的列表,您可以对其进行编辑,以便在未指定任何扩展名的情况下查找其他扩展名(并不是说这是个好主意,提个醒)。 (2认同)