文件在不同操作系统上提供不同的 Mime 类型

文件在不同操作系统上提供不同的 Mime 类型

所以我有一个 bash 脚本,它部分执行以下操作:

file -b --mime-type "$1"

然后我有逻辑检查它是否是预期的文件类型。

if [[ $type == "application/gzip" ]]; then
    <stuff>
    exit 0
fi

# basically the else
echo "File type $type not supported"

所以我在 Debian 系统上构建了这个脚本,所有的逻辑都运行良好。然而,当一位同事询问他是否可以在他正在使用的某些系统(基于 CentOS)上使用它时,他不断收到以下错误输出:

File type application/x-gzip not supported

剧本曾是旨在可移植,因此使用 bash 和 file 等。我尝试在CentOS系统上查看/usr/share/magic,似乎是纯文本。然而,在 Debian 上,它是二进制格式,并且更难以交互。

所以我的理解是,通过调用---mime-type,这将在每个操作系统上每次显示相同的 mime 类型。我知道我可以将 the 添加application/x-gzip到 if 语句中,但如果有办法使输出一致,我宁愿将其作为一种选择。另外,如果我将来向这个脚本添加其他部分,或者将其用作将来工作的模板,我希望有一种方法可以跨操作系统获得一致的输出,这样我就不必担心许多边缘问题案例。

如果有办法获得一致的答案,我可以更改为文件以外的其他内容。

提前致谢。

编辑#00

我最初将 IANA 作为参考,但后来意识到有很多类型是 IANA 无法识别的。这当然会让事情变得更糟。

至于你对版本差异的建议,我认为这可能是根本原因,因为 Debian 系统处于以下位置:

redacted@redacted ~$ file -v
file-5.35
magic file from /etc/magic:/usr/share/misc/magic

而 CentOS 系统位于:

redacted@redacted ~$ file -v
file-5.11
magic file from /etc/magic:/usr/share/misc/magic

至于 strace 的测试,它确实显示(以及上面两个环境的备份)正在读取 /etc/magic 中的文件,并且在 CentOS 的情况下,该文件是纯文本的。 strace 看起来像:

strace -e trace=stat,open,openat file -i bob.txt
open("/usr/lib64/tls/x86_64/libmagic.so.1", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
stat("/usr/lib64/tls/x86_64", 0x7fff0427d1d0) = -1 ENOENT (No such file or directory)
open("/usr/lib64/tls/libmagic.so.1", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
stat("/usr/lib64/tls", {st_mode=S_IFDIR|0555, st_size=4096, ...}) = 0
open("/usr/lib64/x86_64/libmagic.so.1", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
stat("/usr/lib64/x86_64", 0x7fff0427d1d0) = -1 ENOENT (No such file or directory)
open("/usr/lib64/libmagic.so.1", O_RDONLY|O_CLOEXEC) = 3
open("/usr/lib64/tls/libz.so.1", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
open("/usr/lib64/libz.so.1", O_RDONLY|O_CLOEXEC) = 3
open("/usr/lib64/tls/libc.so.6", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
open("/usr/lib64/libc.so.6", O_RDONLY|O_CLOEXEC) = 3
open("/usr/lib/locale/locale-archive", O_RDONLY|O_CLOEXEC) = 3
stat("/root/.magic.mgc", 0x7fff0427e750) = -1 ENOENT (No such file or directory)
stat("/root/.magic", 0x7fff0427e750)    = -1 ENOENT (No such file or directory)
stat("/etc/sysconfig/64bit_strstr_via_64bit_strstr_sse2_unaligned", 0x7fff0427dcb0) = -1 ENOENT (No such file or directory)
open("/etc/magic.mgc", O_RDONLY)        = -1 ENOENT (No such file or directory)
stat("/etc/magic", {st_mode=S_IFREG|0644, st_size=111, ...}) = 0
open("/etc/magic", O_RDONLY)            = 3
open("/usr/share/misc/magic.mgc", O_RDONLY) = 3
open("/usr/lib64/gconv/gconv-modules.cache", O_RDONLY) = 3
stat("bob.txt", {st_mode=S_IFREG|0644, st_size=19, ...}) = 0
open("bob.txt", O_RDONLY)               = 3
bob.txt: text/troff; charset=us-ascii
+++ exited with 0 +++

不要介意 troff 和 .txt 不匹配,这是故意的。选择 TROFF 是因为它不仅仅是纯文本......

我会看看我的同事是否可以在 CentOS 机器上更新文件版本,看看结果是否更好。

编辑#01

因此,在研究另一个工具 xdg-mime 时,我发现在该程序中(至少),x-gzip 和 gzip 之间似乎没有功能差异。

xdg-mime 类型的源代码,ll。 2427-35

它似乎被认为是该程序中的别名(我正在研究该程序是否有独立的魔法存储来解决这个问题)。因此,魔法文件中存在这两种变体似乎很常见。

答案1

IANAapplication/gzip已于 2012 年做出定义。

但对于 HTTP 来说,有这样的注释:

[...] 或与以前的 HTTP 实现的兼容性,应用程序应该将“x-gzip”和“x-compress”分别视为相当于“gzip”和“compress”。

但这是针对 HTTP/1.1 的,相当(非常)古老——并且是一个不同的游戏,完全取决于人们使用它的用途。

gzip 本身是 90 年代初的产物,当时有人还说x-可以用于未注册的子类型。

一般来说,两者已经并且正在被使用。如果一个人可以选择我会使用非x-变体。但100%一致性因为由于野兽的本性,这样的事情会非常困难。就像file随着时代的变化而变化一样,其他具有相同功能的工具也会随着时代的变化而变化。

至于标准等。RFC 6838(2013 年 1 月) 强烈地不鼓励使用x-类型。


如果有人看一下file命令就其本身而言,x-gzip被替换为gzip 2019年(从它的外观来看)。

请注意,有一个 BGZF(Blocked gzip)使用 x-gzip以及。那是“更多的”这是可以理解的,因为它是 gzip 的一个变体,尽管与上面提到的 RFC 相冲突。但这些事情又需要很长时间才能到位。它被用于,谁知道,有多少应用程序等等。


确保其一致性的唯一方法是确保跨系统使用相同的数据库。

file使用魔术图案文件 和一个可以当然分发magic.mgc与脚本并说应该将其放入$HOME/.magic或类似的内容 - 或使用-m脚本中的选项(使用这个/这些魔法文件)。如果使用不同版本,可能会出现问题file- 但不确定使用哪个版本等。

魔法文件以文本形式编写,然后编译成 mgc。

file -C -m my-magic-file

但有一个也将其用作纯文本。也许 CentOS 系统上发生了什么? Astrace应该揭示发生了什么,例如

strace -e trace=stat,open,openat file -i foo.ext

很抱歉,如果这变得非常不一致并且到处都是。

答案2

布洛芬已经很好地解释了file它的神奇文件如何工作,所以我将添加一个务实的“我如何让它工作”答案:

使用匹配两个变体的正则表达式匹配 ( =~),而不是精确==匹配 ( )。

if [[ $type =~ ^application/(x-)?gzip$ ]]; then
...
fi

或者(如果你不介意匹配任何事物包含模式“gzip”,其中可能比你想要或期望的更多 - 例如,/etc/mime.types在我的 Debian 系统上列出了“application/tlsrpt+gzip”,这似乎是某种 gzip 压缩的 SMTP TLS 报告...我从未见过,但有一个草稿IETF 标准):

if [[ $type =~ gzip ]]; then
...
fi

相关内容