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

时间:2013-05-26 14:49:30

标签: shell unix binaryfiles

我怎么知道文件是否是二进制文件?

例如,已编译的c文件。

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

13 个答案:

答案 0 :(得分:46)

使用实用程序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

答案 1 :(得分:9)

改编自excluding binary file

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

答案 2 :(得分:9)

我用

! grep -qI . $path

我唯一可以看到的缺点是它会考虑一个空的文件二进制文件,但是又一次,谁来决定这是不是错了?

答案 3 :(得分:4)

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详细了解-Tperldoc -f -X支票。

答案 4 :(得分:3)

BSD grep

这是使用BSD grep(在macOS / Unix上)检查单个文件的简单解决方案:

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

基本上检查文件是否包含NUL字符。

使用此方法,您可以使用find实用程序递归读取所有非二进制文件:

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

甚至更简单地使用grep

grep -rv "\x00" .

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

grep -v "\x00" *

不幸的是,上述示例不适用于GNU grep,但有一种解决方法。

GNU grep

由于GNU grep忽略了NULL字符,因此check for other non-ASCII characters可能会像这样:

$ grep -P "[^\x00-\x7F]" file && echo Binary || echo Text

注意:对于仅包含NULL字符的文件,它不起作用。

答案 5 :(得分: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

答案 6 :(得分:1)

尝试以下命令行:

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

答案 7 :(得分:1)

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

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

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

警告:正如@yugr报告下面的.doc个文件报告的编码为application/mswordbinary。这看起来像一个错误 - mime类型错误地与编码连接。

$ for flag in --mime --mime-type --mime-encoding; do
    echo "$flag"
    file "$flag" /tmp/example.{doc{,x},png,txt}
  done
--mime
/tmp/example.doc:  application/msword; charset=binary
/tmp/example.docx: application/vnd.openxmlformats-officedocument.wordprocessingml.document; charset=binary
/tmp/example.png:  image/png; charset=binary
/tmp/example.txt:  text/plain; charset=us-ascii
--mime-type
/tmp/example.doc:  application/msword
/tmp/example.docx: application/vnd.openxmlformats-officedocument.wordprocessingml.document
/tmp/example.png:  image/png
/tmp/example.txt:  text/plain
--mime-encoding
/tmp/example.doc:  application/mswordbinary
/tmp/example.docx: binary
/tmp/example.png:  binary
/tmp/example.txt:  us-ascii

答案 8 :(得分:1)

RewriteEngine On RewriteRule ^quiz/index.php([^/]*)$ /quiz/quiz.php?q=$1 [L] + cat

假设二进制表示包含NULL字符的文件,则此shell命令可以提供帮助:

grep

或:

(cat -v file.bin | grep -q "\^@") && echo Binary || echo Text

这是grep -q "\x00"的解决方法,适用于BSD grep,但不适用于GNU版本。

grep -q "\^@" <(cat -v file.bin) && echo Binary 基本上-v会转换所有非打印字符,因此它们以控制字符的形式显示,例如:

cat

其中$ printf "\x00\x00" | hexdump -C 00000000 00 00 |..| $ printf "\x00\x00" | cat -v ^@^@ $ printf "\x00\x00" | cat -v | hexdump -C 00000000 5e 40 5e 40 |^@^@| 个字符代表NULL字符。因此,一旦找到这些控制字符,我们假设该文件是二进制文件。

上述方法的缺点是,当字符不表示控制字符时,它可能会产生误报。例如:

^@

另请参阅:How do I grep for all non-ASCII characters

答案 9 :(得分:0)

使用tr -d "[[:print:]\n\t]" < file | wc -c排除二进制文件是一种蛮力,但它也不是启发式猜测。

find . -type f -maxdepth 1 -exec /bin/sh -c '
   for file in "$@"; 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 "$@"; 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
' _ '{}' + 

答案 10 :(得分:0)

答案 11 :(得分:0)

grep

假设二进制表示包含不可打印字符的文件(不包括空格,制表符或换行符等空白字符),这可能有用(BSD和GNU):

$ grep '[^[:print:][:blank:]]' file && echo Binary || echo Text

注意:GNU grep会将仅包含NULL字符的文件报告为文本,但它可以在BSD version上正常工作。

有关更多示例,请参阅:How do I grep for all non-ASCII characters

答案 12 :(得分:0)

也许这就足够了。

if ! file /path/to/file | grep -iq ASCII ; then
    echo "Binary"
fi

if file /path/to/file | grep -iq ASCII ; then
    echo "Text file"
fi