尝试查找仅包含 NUL 的文件,但得到一些其他文件

尝试查找仅包含 NUL 的文件,但得到一些其他文件

我尝试查找/列出的文件是:

  • 任意大小(接受 0 字节)
  • 仅由 ASCII NUL 字符 (0x00) 组成
  • 如果有除 0x00 以外的任何字符,则不应列出该文件。

我现在的命令是:

grep -RLP '[^\x00]' .

它可以工作,但它也找到仅由两个字节组成的文件:0xFF,0xFE。不知道为什么。

有没有更好的命令来查找这样的文件?

答案1

简而言之,这里发生的事情是grep试图将您的文件解释为 Unicode 数据。序列 0xFF、0xFE 是UTF-16 的字节顺序标记

(在我的测试中,即使涉及两个 0xFF 或两个 0xFE 等的其他序列仍然与'[^\x00]'正则表达式不匹配,因为即使尝试执行 UTF-8,这些也会被视为非字符。)

使用不使用 Unicode 作为字符类型的语言环境应该可以解决这个问题,你可以通过设置LC_CTYPE 环境变量. 使用C语言环境强制使用 ASCII 编码(因此不启用 Unicode):

LC_CTYPE=C grep -RLP '[^\x00]' .

更新:正如@steeldriver 指出的那样,grep 仍然逐行执行,因此包含 NUL 字节和换行符的文件仍然会匹配。

@DavidFoerster 使用 grep 的解决方案-z很好地解决了这个问题,使用 NUL 字节作为分隔符就可以了。

另外,我编写了一个简短的 Python 3 脚本(allzeroes.py)来检查文件的内容是否全为零:

#!/usr/bin/python3
import sys
assert len(sys.argv) == 2
with open(sys.argv[1], 'rb') as f:
    for block in iter(lambda: f.read(4096), b''):
        if any(block):
            sys.exit(1)

您可以使用它来find递归地查找所有匹配项:

$ find . -type f -exec allzeroes.py {} \; -print

我希望这能有所帮助。

答案2

您可以滥用 的grep替代空终止行模式,从而搜索仅包含空行的文件:

grep -L -z -e . ...

替换...为您要扫描的文件集(此处-R .:)。

解释

  • -z, --null-data– 将输入视为一组行,每行以零字节(ASCII NUL 字符)结束,而不是换行符。1
  • -e .– 用作.搜索模式,即匹配任何字符。
  • -L, --files-without-match– 抑制正常输出;而是打印每个通常不会打印输出的输入文件的名称。扫描将在第一次匹配时停止。1

测试用例

设置:

: > empty
truncate -s 100 zero
printf '%s\0' foo bar > foobar

运行测试:

$ grep -L -z -e . empty zero foobar
empty
zero

1grep(1)手册页

答案3

我将提供另一个答案,即我正在使用的脚本。从特定文件夹运行将递归并列出所有 NUL 文件:

shopt -s globstar
for file in ./**
do
    [ -d "$file" ] || LC_CTYPE=C grep -qP '[^\x00]' "$file" || echo "$file"
done

答案4

您可以使用此 PHP 代码查找所有具有 NULL 内容的文件。

<?php
$pattern = '';
$directory = new RecursiveDirectoryIterator("./");
$iterator = new RecursiveIteratorIterator($directory);
if ($pattern) {
    $regex = new RegexIterator($iterator, $pattern);
} else {
    $regex = $iterator;
}
foreach($regex as $file) {
    if (is_dir($file)) continue;
    $contens = file_get_contents($file);
    $contens = trim($contens);
    if (strlen($contens) == 0) {
        echo "$file\n";
    }
}

相关内容