跳转到内容

file

file 用于判断文件的实际类型。Linux 不靠扩展名认类型,.txt 结尾的可以是张图片,没有后缀的可以是可执行文件 —— file 读的是内容。

Terminal window
file [选项] 文件...

输出格式是 文件名: 类型描述 文件不存在或没有读权限时也会照常输出一行,说明是哪种错误

file 按顺序做三类测试,第一个命中的就是结果:

  1. 文件系统测试:调 stat,先分出目录、软链接、设备文件、空文件这些不用看内容就能判定的类型
  2. 魔数测试:读文件开头的若干字节,拿去和特征库比对。特征库是 /usr/share/misc/magic.mgc 一类的编译产物,PNG 开头是 89 50 4E 47、ELF 开头是 7F 45 4C 46,都记在里面
  3. 语言测试:前两步都不匹配就当文本处理,进一步猜字符编码,以及是不是某种脚本或源码

判断依据全在内容里,所以改扩展名骗不过它,但反过来,故意伪造开头字节也能骗过它

选项 说明
-b 只输出类型,不带文件名前缀(brief)
-i 输出 MIME 类型而不是描述文字(mime)
--mime-type 只输出 MIME 的类型部分,不带字符集
-L 跟随软链接,报告目标文件的类型
-z 顺带看压缩包内部的内容类型
-s 读块设备、字符设备的内容,不止报告「是个设备」
-f <文件> 从文件里逐行读要检查的路径
--extension 输出该类型常见的扩展名
-k 不在第一次命中后停下,把所有匹配都列出来

1. 基本判断

Terminal window
file note.md logo.png run.sh

输出:

note.md: ASCII text
logo.png: PNG image data, 800 x 600, 8-bit/color RGBA, non-interlaced
run.sh: Bourne-Again shell script, ASCII text executable

2. 扩展名不可信

Terminal window
mv logo.png logo.txt
file logo.txt

输出:

logo.txt: PNG image data, 800 x 600, 8-bit/color RGBA, non-interlaced

3. 拿 MIME 类型

Terminal window
file -i note.md
file --mime-type -b note.md

输出:

note.md: text/plain; charset=us-ascii
text/plain

脚本里做分支判断用 --mime-type -b,输出干净、好比较

4. 看可执行文件的细节

Terminal window
file /bin/ls

输出:

/bin/ls: ELF 64-bit LSB pie executable, x86-64, dynamically linked,
interpreter /lib64/ld-linux-x86-64.so.2, BuildID[sha1]=..., stripped

一行里能读出位数、动态还是静态链接、有没有被 strip stripped 意味着符号表已经去掉,这种二进制用 gdb 调试是看不到函数名的,见 gdb

5. 批量检查

Terminal window
find . -type f -exec file {} +
file -f paths.txt

-exec ... + 会把多个路径攒到一条命令里,比一个文件起一次进程快得多,见 find

  • man file
  • man 5 magic(特征库的格式)