2013-05-26 58 views
34

如何知道文件是否是二进制文件?如何检查文件是否是二进制文件并读取所有不是的文件?

例如,编译的C文件。

我想从某个目录读取所有文件,但我想忽略二进制文件。

+8

最终*所有*是二进制文件。文本文件恰好包含人类可读字符数据的二进制表示。没有任何方法可以将文本与非文本区分开100%可靠。 –

+0

[在Vim中类似](http://vi.stackexchange.com/q/3206/467) – kenorb

回答

35

使用的工具file,样品用量:

$ file /bin/bash 
/bin/bash: Mach-O universal binary with 2 architectures 
/bin/bash (for architecture x86_64): Mach-O 64-bit executable x86_64 
/bin/bash (for architecture i386): Mach-O executable i386 

$ file /etc/passwd 
/etc/passwd: ASCII English text 

$ file code.c 
code.c: ASCII c program text 

file manual page

+4

考虑使用'file --mine'。对于二进制文件,它会报告“... charset = binary”,所以可以简单地grep for正则表达式“binary $”。 – 4dan

+8

@ 4dan - 也许'--mime'? :) – Bach

+0

@ 4dan对我有用:'file -bL --mime“$ path”| grep -q'^ text''。选项'-b'从输出中删除文件名,而'-L'则解引用符号链接。 – wjandrea

8

改编自excluding binary file

find . -exec file {} \; | grep text | cut -d: -f1 
+0

这应该是'grep文本';历史上,'file'并不总是说ASCII,而是例如“shell脚本文本”。 – Jens

+0

@Jens感谢提醒。只需检查'file'手册页,它应该是'text'。 – gongzhitaao

+0

我刚刚意识到,再次重新发明了轮子: 用于'查找文件。 -type f -exec file {} \; | grep文本| perl -nle'split /:/; print $ _ [0]'';做grep -i --color'string_to_search'$ file;完成; –

2

使用Perl的内置-T文件测试操作,最好确定这是一个后使用-f文件测试运算符的纯文件:

$ perl -le 'for (@ARGV) { print if -f && -T }' \ 
    getwinsz.c a.out /etc/termcap /bin /bin/cat \ 
    /dev/tty /usr/share/zoneinfo/UTC /etc/motd 
getwinsz.c 
/etc/termcap 
/etc/motd 

下面是集合的补:

$ perl -le 'for (@ARGV) { print unless -f && -T }' \ 
    getwinsz.c a.out /etc/termcap /bin /bin/cat \ 
    /dev/tty /usr/share/zoneinfo/UTC /etc/motd 
a.out 
/bin 
/bin/cat 
/dev/tty 
/usr/share/zoneinfo/UTC 
3
perl -E 'exit((-B $ARGV[0])?0:1);' file-to-test 

可以用来检查时“文件 - 测试”是二进制的。上面的命令将在二进制文件退出机智码0,否则退出代码是1

文本文件反向检查可以像下面的命令:

perl -E 'exit((-T $ARGV[0])?0:1);' file-to-test 

同样,上面的命令将退出如果“文件测试”是文本(不是二进制),则为0。

了解更多关于-B-T使用命令perldoc -f -X进行检查。

+0

http://perldoc.perl.org/functions/-X.html – Onlyjob

0

这是一种强力排除与tr -d "[[:print:]\n\t]" < file | wc -c二进制文件,但它是没有启发式猜测要么。

find . -type f -maxdepth 1 -exec /bin/sh -c ' 
    for file in "[email protected]"; do 
     if [ $(LC_ALL=C LANG=C tr -d "[[:print:]\n\t]" < "$file" | wc -c) -gt 0 ]; then 
     echo "${file} is no ASCII text file (UNIX)" 
     else 
     echo "${file} is ASCII text file (UNIX)" 
     fi 
    done 
' _ '{}' + 

不过,下面的使用grep -a -m 1 $'[^[:print:]\t]' file的蛮力方法看起来好快得多。

find . -type f -maxdepth 1 -exec /bin/sh -c ' 
    tab="$(printf "\t")" 
    for file in "[email protected]"; do 
     if LC_ALL=C LANG=C grep -a -m 1 "[^[:print:]${tab}]" "$file" 1>/dev/null 2>&1; then 
     echo "${file} is no ASCII text file (UNIX)" 
     else 
     echo "${file} is ASCII text file (UNIX)" 
     fi 
    done 
' _ '{}' + 
1

请尝试以下命令行:

file "$FILE" | grep -vq 'ASCII' && echo "$FILE is binary" 
+0

不错,但被urt8 ascii文件愚弄。我用:文件“$ FILE”| grep -vq'文字' –

6

我用

! grep -qI . $path 

唯一的缺点我能看到的是,它会考虑一个空文件二进制但话又说回来,谁决定如果这是错误的?

3

不理想,但简单的解决方案来检查单个文件:

grep -q "\x00" file.bin && echo Binary file. || echo Text file. 

如果这些文件由NULL字符这基本上检查。

所以读递归使用find程序中的所有非二进制文件,你可以这样做:

find . -type f -exec sh -c 'grep -q "\x00" {} || cat {}' ";" 

或者更简单的只用grep

grep -rv "\x00" . 

对于刚刚当前文件夹,使用:

grep -v "\x00" * 
1

关闭Bach's suggestion,我认为--mime-encoding是从file获得可靠信息的最佳标志。

file --mime-encoding [FILES ...] | grep -v '\bbinary$' 

将打印文件file认为具有非二进制编码。如果您只需要文件名,则可以通过cut -d: -f1管道输出来修剪: encoding

相关问题