标准 Unix 实用程序如grep
和diff
使用一些启发式方法将文件分类为“文本”或“二进制”。 (例如,grep
的输出可能包括像这样的行Binary file frobozz matches
。)
是否有一种方便的测试可以在zsh
脚本中应用来执行类似的“文本/二进制”分类? (除了类似的东西grep '' somefile | grep -q Binary
。)
(我意识到任何这样的测试都必然是启发式的,因此并不完美。)
答案1
如果您file
只要求哑剧类型你会得到很多不同的,比如text/x-shellscript
,等等application/x-executable
,但我想如果你只检查“文本”部分,你应该会得到很好的结果。例如(-b
输出中没有文件名):
file -b --mime-type filename | sed 's|/.*||'
答案2
另一种方法是isutf8
使用更多实用程序收藏。
如果文件是有效的 UTF-8 或 ASCII,或者短路,则以 0 退出,-q
并打印一条错误消息(以 沉默),否则以 1 退出。
答案3
如果您喜欢 GNU 使用的启发式grep
,您可以使用它:
isbinary() {
LC_MESSAGES=C grep -Hm1 '^' < "${1-$REPLY}" | grep -q '^Binary'
}
它在从文件读取的第一个缓冲区中搜索 NUL 字节(对于常规文件来说是几千字节,但对于管道或套接字或某些设备(例如/dev/random
)可能要少得多)。在 UTF-8 语言环境中,它还会标记不形成有效 UTF-8 字符的字节序列。它假设LC_ALL
未设置为语言不是英语的内容。
该${1-$REPLY}
形式允许您将其用作zsh
全局限定符:
ls -ld -- *(.+isbinary)
会列出二进制文件。
答案4
file
有一个--mime-encoding
尝试检测文件编码的选项。
$file --mime-encoding Documents/poster2.pdf
Documents/poster2.pdf: binary
$file --mime-encoding projects/linux/history-torvalds/Makefile
projects/linux/history-torvalds/Makefile: us-ascii
$file --mime-encoding graphe.tex
Dgraphe.tex: us-ascii
$file --mime-encoding software.tex
software.tex: utf-8
您可以使用file --mime-encoding | grep binary
它来检测文件是否是二进制文件。它工作可靠,尽管它可能会被长文本文件中的单个无效字符混淆。
例如,我cat
为以下 shell 脚本添加别名,以避免无意中打开二进制文件而破坏我的终端:
#! /bin/sh -
[ ! -t 1 ] && exec /bin/cat "$@"
for i
do
if file --mime-encoding -- "$i" | grep -q binary
then
hexdump -C -- "$i"
else
/bin/cat -- "$i"
fi
done