2013-05-26 60 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

相關問題