簡體   English   中英

如何在linux中區分文本文件中的二進制文件

[英]How to tell binary from text files in linux

linux file命令在識別文件類型方面做得非常好,並給出了非常細粒度的結果。 diff工具能夠區分二進制文件和文本文件,產生不同的輸出。

有沒有辦法告訴二進制文件形成文本文件? 我想要的只是一個是/否的答案是否給定的文件是二進制的。 因為很難定義二進制,所以假設我想知道diff是否會嘗試基於文本的比較。

澄清這個問題:我不在乎它是 ASCII 文本還是 XML,只要它是文本。 另外,我不想區分 MP3 和 JPEG 文件,因為它們都是二進制文件。

file仍然是您想要的命令。 任何文本文件(根據其啟發式)將在file的輸出中包含單詞“text”; 任何二進制的東西都不會包含“文本”這個詞。

如果您不同意file用於確定文本與非文本的啟發式方法,則需要更好地指定問題,因為文本與非文本本質上是一個模糊的問題。 例如, file不會將 ASCII 中的 PGP 公鑰塊標識為“文本”,但您可以(因為它僅由可打印的字符組成,即使它不是人類可讀的)。

diff 手冊指定

diff 通過檢查文件的前幾個字節來確定文件是文本文件還是二進制文件; 確切的字節數取決於系統,但通常為數千。 如果文件該部分中的每個字節都不為空,則 diff 認為該文件是文本; 否則它認為文件是二進制的。

一種快速而骯臟的方法是在文件的前 K 或前兩個中查找NUL字符(零字節)。 只要您不擔心 UTF-16 或 UTF-32,任何文本文件都不應該包含NUL

更新:根據 diff 手冊,這正是 diff 所做的。

你可以嘗試給一個

strings yourfile

命令並將結果的大小與文件大小進行比較......我不完全確定,但如果它們相同,則該文件實際上是一個文本文件。

這種方法在確定文件是二進制文件還是文本文件時遵循grep命令:

is_text_file() { grep -qIF '' "$1"; }

使用的 grep 選項:

  • -q安靜; 如果找到任何匹配項,立即以零狀態退出
  • -I處理一個二進制文件,就好像它不包含匹配的數據一樣
  • -F PATTERNS 解釋為固定字符串,而不是正則表達式。

使用的 grep 模式:

  • ''空字符串。 所有文件(空文件除外)都將匹配此模式。

筆記

  • 根據此測試,空文件不被視為文本文件。 (GNU file命令同意這個評估。)
  • 根據此測試,具有一個可打印字符的文件(例如a )被視為文本文件。 (對我來說很有意義。)file命令不同意這個評估。(用 GNU file測試))
  • 這種方法只需要一個子進程來測試文件是文本文件還是二進制文件。

測試

# cd into a temp directory
cd "$(mktemp -d)"

# Create 3 corner-case test files
touch empty_file       # An empty file
echo -n a >one_byte_a  # A file containing just `a`
echo a >one_line_a     # A file containing just `a` and a newline

# Another test case: a 96KiB text file that ends with a NUL
head -c 98303 /usr/share/dict/words > file_with_a_null_96KiB
dd if=/dev/zero bs=1 count=1 >> file_with_a_null_96KiB

# Last test case: a 96KiB text file plus a NUL added at the end
head -c 98304 /usr/share/dict/words > file_with_a_null_96KiB_plus1
dd if=/dev/zero bs=1 count=1 >> file_with_a_null_96KiB_plus1

# Defer to grep to determine if a file is a text file
is_text_file() { grep -qI '^' "$1"; }

# Test harness
do_test() {
  printf '%22s ... ' "$1"
  if is_text_file "$1"; then
    echo "is a text file"
  else
    echo "is a binary file"
  fi
}

# Test each of our test cases
do_test empty_file
do_test one_byte_a
do_test one_line_a
do_test file_with_a_null_96KiB
do_test file_with_a_null_96KiB_plus1

輸出

            empty_file ... is a binary file
            one_byte_a ... is a text file
            one_line_a ... is a text file
file_with_a_null_96KiB ... is a binary file
file_with_a_null_96KiB_plus1 ... is a text file

在我的機器上,似乎 grep 檢查文件的前 96 KiB 是否為NUL (用 GNU grep測試)。 確切的交叉點取決於您機器的頁面大小。

相關源碼: https : //git.savannah.gnu.org/cgit/grep.git/tree/src/grep.c?h=v3.6#n1550

如今,術語“文本文件”含糊不清,因為文本文件可以用 ASCII、ISO-8859-*、UTF-8、UTF-16、UTF-32 等編碼。

請參閱此處了解 Subversion 如何做到這一點。

在 ubuntu 中執行此操作的一種快速方法是在“列表”視圖中使用 nautilus。 類型列將顯示它是文本還是二進制

像less、grep這樣的命令很容易(而且很快)檢測到它。 你可以看看他們的來源。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM