简单的前言
虽然这里的日期是 2024-03-20,但是我写这篇博客的时候其实是 2025-02-18,来自我的计算机系统的讨论课材料. 如果你想知道一个文件的类型,那么你可能会用到 file
这个命令,file
会告诉你这个文件的类型,那么 file
是如何知道文件的类型的,或者说,系统中的文件如何告诉 file
(或者任意一个想知道其类型的程序)自己的类型,文件把类型的信息放在哪里?
阅读手册
了解一个命令的第一二三个手段一般是 whatis
/ man
/ tldr
.
man whatis
会告诉你,whatis
其实就来自 man
:
Each manual page has a short description available within it. whatis searches the manual page names and displays the manual page descriptions of any name matched.
man file
会告诉你,file
这样检查文件的类型:
file tests each argument in an attempt to classify it. There are three sets of tests, performed in this order: filesystem tests, magic tests, and language tests. The first test that succeeds causes the file type to be printed.
- filesystem tests
系统调用 stat, 根据其返回值判断文件的类型;stat 可以判断文件为空/文件类型是<sys/stat.h>中已定义的类型. - magic tests
检查文件头是否含有特定的 magic bytes. 例如,如果该文件的前五个字节对应的 ASCII 字符是"%PDF-",则判断为PDF文件. 若不存在任何 magic bytes, 则判断为文本文件,file
将继续判断其编码方式为 ASCII/UTF-8/… - language tests
通过关键字判断文件的语言,如从 main, struct, printf 推测该文本文件为 C 源文件.
近距离观察这个命令的执行流程的方式是 strace file foo.bar
;你也可以把输出放到重定向到文件里,然后用 vim
查看它,以便进行关键字检索,如 strace file foo.bar &> strace.out; vim strace.out
–>
欺骗 file
从 magic test 入手

从 language test 入手

简单的结语
回答最开始的问题——file
通过 filesystem tests, magic tests, and language tests 得知文件的类型,文件通过文件头中的 magic byte / 文本编码 / 程序语言关键字来表达自己的类型.