问题描述
Linux通过file-header中的代码确定文件的类型。它不依赖于file-extensions来了解用于打开文件的软件。
这就是我从教育中记得的东西。如果我错了,请纠正我!
最近在Ubuntu系统上工作了一下:我看到系统上的很多文件都有扩展,如.sh
,.txt
,.o
,.c
现在我想知道:这些扩展仅适用于人类吗?那么人们应该知道它是什么类型的文件?
或者它们对operating-system有什么用途吗?
最佳解决方法
Linux determines the type of a file via a code in the file header. It doesn’t depend on file extensions for to know with software is to use for opening the file.
That’s what I remember from my education. Please correct me in case I’m wrong!
-
正确记住。
Are these extensions are meant only for humans?
-
是的,有一个但是。
当您与依赖于扩展的其他操作系统进行交互时,使用它们是更明智的想法。
在Windows中,打开软件附加到扩展。
在Windows中打开一个名为”file”的文本文件比打开名为”file.txt”的同一文件更困难(每次都需要将文件打开对话框从*.txt
切换到*.*
)。 TAB和semi-colon分离的文本文件也是如此。导入和导出e-mails(.mbox扩展名)也是如此。
特别是在编写软件代码时。与”software.html”和”software.js”相比,打开作为HTML文件的名为”software1″的文件和作为JavaScript文件的”software2″变得更加困难。
如果在Linux中有一个文件扩展名很重要的系统,我会称之为bug。当软件依赖于文件扩展名时,这是可利用的。我们使用interpreter directive来识别文件是什么(“文件中的前两个字节可以是字符”#!”,它构成一个幻数(十六进制23和21,”#”和”!”的ASCII值),通常称为shebang, “)。
文件扩展名最着名的问题是Windows上的LOVE-LETTER-FOR-YOU.TXT.vbs。这是一个可视化的基本脚本,在文件资源管理器中显示为文本文件。
在Ubuntu中,当您从Nautilus启动文件时,您会收到警告它将要执行的操作。从Nautilus执行一个脚本,它想要启动一个应该打开gEdit的软件,这显然是一个问题,我们会收到一个警告。
在命令行执行某些操作时,您可以直观地看到扩展名是什么。如果它以.vbs结束,我会开始变得怀疑(不是说.vbs在Linux上是可执行的。至少不会没有更多的努力;))。
次佳解决方法
这里没有100%的黑色或白色答案。
通常Linux不依赖于文件名(和文件扩展名,即通常最后一段时间后文件名的一部分),而是通过检查其内容的前几个字节并将其与已知magic numbers列表进行比较来确定文件类型。
例如,所有位图图像文件(通常名称扩展名为.bmp
)必须以前两个字节中的字母BM
开头。大多数脚本语言中的脚本,如Bash,Python,Perl,AWK等(基本上所有处理以#
开头的行作为注释的内容)可能包含像#!/bin/bash
一样的shebang作为第一行。此特殊注释告诉系统使用哪个应用程序打开文件。
因此,通常操作系统依赖于文件内容而不是其名称来确定文件类型,但是说明在Linux上永远不需要文件扩展名只是事实的一半。
应用程序当然可以实现他们想要的文件检查,包括验证文件名和扩展名。一个例子是Eye of Gnome(eog
,标准图片查看器),它通过文件扩展名确定图像格式,如果与内容不匹配则抛出错误。可以讨论这是一个错误还是一个功能……
但是,即使操作系统的某些部分依赖于文件扩展名,例如解析/etc/apt/sources.list.d/
中的软件源文件时 – 只解析具有*.list
扩展名的文件,忽略所有其他文件。它可能不是主要用于确定文件类型,而是启用/禁用某些文件的解析,但它仍然是影响系统处理文件方式的文件扩展名。
当然,人类用户从文件扩展中获利最多,因为它使文件的类型显而易见,并且还允许具有相同基本名称和不同扩展名的多个文件,如site.html
,site.php
,site.js
,site.css
等。缺点当然是文件扩展名和实际文件类型/内容不一定必须匹配。
另外,cross-platform互操作性需要它,例如, Windows不知道如何处理readme
文件,而只知道readme.txt
。
第三种解决方法
正如其他人所提到的,在Linux中使用了一个解释器指令方法(将一些元数据存储在文件中作为标题或幻数,以便正确的解释器可以被告知读取它)而不是Windows使用的文件扩展名关联方法。
这意味着您可以创建几乎任何您喜欢的名称的文件…… with a few exceptions
However
我想补充一点。
如果您的系统上有一些文件来自使用文件名关联的系统,则这些文件可能没有那些神奇的数字或标题。文件扩展名用于通过能够读取它们的应用程序来标识这些文件,如果重命名此类文件,则可能会遇到一些意外的影响。例如:
如果你将文件My Novel.doc
重命名为My-Novel
,Libreoffice仍然可以打开它,但它将打开为’Untitled’,你必须再次命名才能保存它(Libreoffice默认添加一个扩展名,所以你会有两个文件My-Novel
和My-Novel.odt
,这可能很烦人)
更严重的是,如果您将文件My Spreadsheet.xlsx重命名为My-Spreadsheet,然后尝试使用xdg-open My-Spreadsheet
打开它,您将得到此信息(因为它实际上是一个压缩文件):
如果您将文件My Spreadsheet.xls
重命名为My-Spreadsheet
,当您xdg-open My-Spreadsheet
时会出现错误说
error opening location: No application is registered as handling this file
(虽然在这两种情况下,如果你做soffice My-Spreadsheet
它可以正常工作)
如果您随后使用mv
将无扩展名文件重命名为My-Spreadsheet.ods
并尝试打开它,您将得到:
(修复失败)
并且您必须重新打开原始扩展名才能正确打开文件(如果愿意,您可以转换格式)
长话短说:
如果你有带名称扩展名的non-native文件,请不要删除扩展名,假设一切正常!
第四种方法
我想从其他答案中采取不同的方法,并挑战”Linux”或”Windows”与此有关的概念(请耐心等待)。
文件扩展名的概念可以简单地表示为“基于其名称的一部分来识别文件类型的约定”。用于识别文件类型的其他常见约定是将其内容与已知签名的数据库(“magic number”方法)进行比较,并将其作为额外属性存储在文件系统上(原始MacOS中使用的方法)。
由于Windows或Linux系统上的每个文件都有名称和内容,因此想要了解文件类型的进程可以使用”extension”或”magic number”方法。元数据方法通常不可用,因为在大多数文件系统上没有此属性的标准位置。
在Windows上,传统上使用文件扩展名作为识别文件的主要手段;最明显的是,图形文件浏览器(Windows 3.1上的文件管理器和现代Windows上的资源管理器)在文件上使用double-click来确定要启动的应用程序时使用它。在Linux(以及更一般地说,Unix-based系统)上,检查内容的传统更多;最值得注意的是,内核查看直接执行的文件的开头以确定如何运行它;脚本文件可以指示要使用的解释器,方法是从#!
开始,然后是解释器的路径。
这些传统影响了为每个系统编写的程序的UI设计,但是有很多例外,因为每种方法在不同情况下都有利有弊。使用文件扩展名而不是检查内容的原因包括:
-
与检查文件名相比,检查文件内容相当昂贵;所以例如“查找名为* .conf的所有文件”将比“查找第一行与此签名匹配的所有文件”快得多
-
文件内容可能含糊不清;许多文件格式实际上只是以特殊方式处理的文本文件,许多其他文件格式是specially-structured zip文件,并且为这些文件定义准确的签名可能很棘手
-
一个文件真的可以作为多种类型有效; HTML文件也可以是有效的XML,zip文件和连接在一起的GIF对两种格式都有效
-
幻数匹配可能导致误报;没有标题的文件格式可能会以字节”GIF89a”开头并被误认为是GIF图像
-
重命名文件可以方便地将其标记为”disabled”;例如将”foo.conf”更改为”foo.conf~”以指示备份比编辑文件更容易注释掉其所有指令,并且比将其移出自动加载目录更方便;类似地,将.php文件重命名为.txt将告诉Apache将其源作为纯文本提供,而不是将其传递给PHP引擎
默认情况下使用文件名的Linux程序示例(但可能还有其他模式):
-
gzip和gunzip对任何以”.gz”结尾的文件进行特殊处理
-
gcc将”.c”文件作为C处理,”.cc”或”.C”作为C++处理
第五种方法
实际上,有些技术确实依赖于文件扩展,所以如果你在Ubuntu中使用这些技术,你也必须依赖扩展。几个例子:
-
gcc
使用扩展来区分C和C++文件。没有扩展,几乎不可能区分它们(想象一下没有类的C++文件)。 -
许多文件(
docx
,jar
,apk
)只是特别结构化的ZIP档案。虽然您通常可以从内容推断出类型,但可能并不总是可行(例如,Java Manifest是jar
文件中的optional)。
在这种情况下不使用文件扩展名只能使用hacky变通方法,并且很可能是非常error-prone。
第六种方法
您的第一个假设是正确的:Linux上的扩展无关紧要,只对人类(以及其他关心扩展的non-Unix-like操作系统)有用。文件的类型由文件中的前32位数据确定,称为magic number这就是shell脚本需要#!
行 – 告诉操作系统要调用的解释器。没有它,shell脚本只是文本文件。
就文件管理器而言,他们确实想知道某些文件的扩展名,例如.desktop
文件,这些文件基本上与Window的快捷方式版本相同,但具有更多功能。但就操作系统而言,它需要知道文件中的内容,而不是其名称中的内容
第七种方法
这对评论答案来说太大了。
请记住,即使”extension”有很多不同的含义。
你说的话似乎是之后的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或者没有扩展名对内容有任何意义,但是后面的东西。确实有一些意义。你可能会设置你的SCM忽略main.o和main。
重点在于:扩展不会像在Windows中一样使用。内核不会执行.txt文件,因为您删除了名称的.txt部分。如果设置了执行权限,也很乐意执行.txt文件。话虽如此,它们确实有意义,并且仍然在”computer level”上使用很多东西。