如果不是通过文件后缀,如何知道文件类型?


55

我想知道如果文件名没有后缀的情况下如何知道文件类型。

例如,一个名为的文件myfile可以以二进制或文本开头,系统如何知道该文件是二进制还是文本?


3
只是评论,其余的答案涵盖了所有内容。如今,可能发生的情况是,使用错误配置的语言环境或旧的可执行文件,由于非ASCII字节,某些utf-8文件可能会被误检测为二进制数据。
Orion 2015年

19
系统不在乎。某些应用程序可能会在意,但是它们各自都有自己的处理方式。
jwodder 2015年

2
请注意,即使对于常规文件(不是设备文件,Unix域套接字,命名管道等),“文件类型”也可以表示两种不同的含义:(1)特定的文件格式(“ .docx”,XML,MS-DOS文本格式) ,RTF,固定长度的记录,列表可能会很长)或(2)某个特定应用程序知道如何处理的文件(“ .xlsx”或“ .doc”或其他任何格式,与格式类型重叠) 。在讨论“文件类型”时,有必要牢记这种区别。
Bruce Ediger 2015年

@jwodder系统确实在乎。该系统抱怨您尝试执行时无法执行不可执行的文件,而不是那些应用程序!
李斯特先生,2015年

1
@MrLister是的,但可执行文件/非可执行文件与“扩展名”无关。
user2338816 2015年

Answers:


84

file实用程序通过3种方式确定文件类型:

首先是文件系统测试:在这些测试中,将对文件调用stat系列系统调用之一。这将返回不同的unix文件类型:常规文件,目录,链接,字符设备,块设备,命名管道或套接字。以此进行魔术测试。

魔术的测试是一个有点复杂。文件类型可以通过称为魔术文件的模式数据库来猜测。某些文件类型可以通过读取文件中特定位置的位或数字来确定(例如,二进制文件)。魔术文件包含“ 魔术数字 ”,以测试文件是否包含魔术数字以及应打印哪些文本信息。那些“ 魔术数字 ”可以是1-4个字节的值,字符串,日期甚至是正则表达式。通过进一步测试,可以找到其他信息。对于可执行文件,附加信息将是是否已动态链接,是否已剥离是不是还是架构。有时,必须通过多个测试才能真正识别文件类型。但是无论如何,执行多少测试都没有关系,这总是一个很好的猜测

以下是一些常见文件类型的文件中的前8个字节,它们可以帮助我们了解这些魔术数字的外观:

             Hexadecimal          ASCII
PNG   89 50 4E 47|0D 0A 1A 0A   ‰PNG|....
JPG   FF D8 FF E1|1D 16 45 78   ÿØÿá|..Ex
JPG   FF D8 FF E0|00 10 4A 46   ÿØÿà|..JF
ZIP   50 4B 03 04|0A 00 00 00   PK..|....
PDF   25 50 44 46|2D 31 2E 35   %PDF|-1.5

如果在魔术测试中找不到文件类型,则该文件似乎是文本文件,并在file寻找内容的编码。编码的区别在于构成每个集合中可打印文本的字节的不同范围和顺序。

还会根据其十六进制值调查换行符:

  • 0A\n)对Un * x / Linux / BSD / OSX终止文件进行分类
  • 0D 0A\r\n)是来自Microsoft操作系统的文件
  • 0D\r)在版本9之前为Mac OS
  • 15\025)将是IBM的AIX

现在开始语言测试。如果它似乎是一个文本文件,则在文件中搜索特定的字符串以找出其包含的语言(C,Perl,Bash)。某些脚本语言也可以通过脚本第一行中的hashbang#!/bin/interpreter)进行标识。

如果文件没有任何内容,则无法确定文件类型,file仅显示“数据”。

因此,您将看到不需要后缀。如果设置错误,后缀还是会造成混淆。


4
还有freedesktop.org共享的MIME数据库,基本上所有X11应用程序都使用该数据库。这在概念上与所file(1)执行的操作类似,但是实现方式非常不同。
lcd047

4
请注意,此过程的结果基本上是猜测,因此不应依赖于任何重要的事情。(方便的功能,例如确定用于打开文件的默认程序,就可以了)
user253751 2015年

因此,如果我在文本文件的顶部添加%PNG,它将被视为png文件。对??
saga

@saga如果您正确编码,并且放了一个千分号而不是百分号,那么:也许。可能还有其他测试。
Bananguin

19

通常,它不在乎。您只需将其传递给程序,它要么解释它,要么不解释。在文本编辑器中打开.jpg可能没有用,但不会阻止您这样做。扩展名与文件名的其余部分一样,是为了方便组织使用。

也可以构造可以多种方式有效解释的文件。因为ZIP文件格式开头是文件末尾的标头,所以您可以将其他内容放在前面,它仍将作为ZIP文件加载。这通常用于制作自解压的zip文件。


4
在最后一段中:Funky File Formats是关于该主题的有趣演讲,例如,它也是一个java hello world程序jpeg,在AES加密后变成PNG,或者在3DES解密后变成PDF,等等(全部具有“有趣的”内容,即不仅具有白噪声或人工制品)
Hagen von Eitzen

14

该信息通常在文件的标题中找到。该file命令将分析目标并告诉您有关文件的信息。很多信息通常来自文件头,通常是文件头几个字节的乘积(请参见下文)。系统使用标头确定如何处理文件。 #!/bin/bash文件开头的内容告诉系统使用bash shell解释以下脚本。ELF告诉系统这是一个ELF可执行文件。

[~] root@www # file /bin/ls
/bin/ls: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked (uses shared libs), for GNU/Linux 2.6.18, stripped

[~] root@www # file /etc/passwd
/etc/passwd: ASCII text

文件头示例:

[root@server4 ~]# xxd old_sm_logo.png | head -5
0000000: 8950 4e47 0d0a 1a0a 0000 000d 4948 4452  .PNG........IHDR
0000010: 0000 0134 0000 006f 0806 0000 0062 bf3c  ...4...o.....b.<

[root@server4 ~]# xxd /bin/ls | head -5
0000000: 7f45 4c46 0201 0100 0000 0000 0000 0000  .ELF............
0000010: 0200 3e00 0100 0000 a024 4000 0000 0000  ..>......$@.....

[root@server4 proj]# xxd resizer.sh | head -5
0000000: 2321 2f62 696e 2f62 6173 680a 5b20 2d7a  #!/bin/bash.[ -z
0000010: 2022 2431 2220 5d20 2626 2065 6368 6f20   "$1" ] && echo

3
这颇具误导性。Unix文件本身没有“标头”。该file命令尝试从文件内容中猜测文件可能打算如何使用。这不是万无一失的。
Nate Eldredge

您正确地解释的行为是正确的file。实际上,它确实对文件进行了分析。但是,大多数文件类型由各种标题标识。 0000000: 7f45 4c46 0201 0100 0000 0000 0000 0000 .ELF............是ELF可执行文件的头(/ bin / ls的前几个字节)。同样#!/bin/bash,在ASCII文件的顶部,会将其标识为Shell脚本。另一个示例:(0000000: 8950 4e47 0d0a 1a0a 0000 000d 4948 4452 .PNG........IHDR
png

2
但是您的答案听起来像是标头是Unix文件的固有功能。例如,文本文件没有这样的标题;像OP这样的人可能会认为C源文件和Java源文件具有不同的“文件类型”,但是没有标头可以区分它们。我认为“文件类型”在Unix下甚至不是一个有意义的概念。操作系统只是提供了一个文件系统,每个应用程序都可以决定任何给定文件的内容是什么意思。
Nate Eldredge

我同意。我试图尽可能简单地回答而又不掉太多兔子洞。
h3rrmiller 2015年

7

首先要检查的是内核识别的硬编码文件类型。这些是文件类型,例如目录,字符专用文件,块专用文件,管道专用文件,套接字和符号链接。此信息来自文件的索引节点。如果文件是纯文件,则通过查找模式,来自下一个256字节的下一组信息。因此,通过检查那些字节可以识别文本文件和C源代码。此外,这些实用程序还会寻找一个魔术数字,该数字用于测试和验证文件类型。您可以通过将信息添加到文件中来添加自己的文件类型以进行识别/etc/magic。请参阅手册页magic(5)以查看魔术文件的格式。

在较早的实现中(例如Solaris),该文件/etc/magic枚举了大多数已识别的文件类型。


4

file命令通过检查文件(的一部分)并进行合格的猜测来应用启发式方法。除此之外,在某些特殊情况下,可以获得更多信息;例如#!文本文件开头的BoM(字节顺序标记)或可执行文件格式的特定标头字节。#!系统使用可执行文件中的和二进制标记来区分它们。


4

系统不知道文件是二进制文件还是文本文件。在所有(AFAIK)Unix类型的操作系统中,fopen(path, "rb")fopen(path "r")- 完全相同- b无效。之所以被接受,是因为标准C需要可移植到其他确实做到这一点的OS。


0

我认为“文件类型”在Unix下甚至不是一个有意义的概念。

在大型机计算机的旧时代,其操作系统支持多种文件类型,包括顺序文件和索引顺序文件。现代操作系统(Un * x和Windows)可以将文件类型的集合减少到最少(包括可执行文件,共享库)。

也可以构造可以多种方式有效解释的文件

可能存在棘手的文件格式:一段C代码可以解释为图像描述。此外,越来越少地有不同的格式:文本文件,XML文件,SOAP文档。


1
随着文件格式的发展,XPM并不是那么棘手。我认为“ tricky”以有效的JPEG和有效的ZIP文件开头。
马克
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.