我尝试查找/列出的文件是:
- 任意大小(接受 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
1从grep(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";
}
}