如何查找内容中包含 100% NUL 字符的文件?

Ada*_*ski 17 command-line grep find

可以识别此类文件的 Linux 命令行命令是什么?

AFAIKfind命令(或grep)只能匹配文本文件的特定字符串。但我想匹配整个内容,即我想查看哪些文件匹配正则表达式\0+忽略行尾字符。也许这个find . cat | grep习语可以工作,但我不知道如何让 grep 忽略行(并将文件视为二进制文件)。

背景:每隔几天,当我的笔记本电脑死机时,我的 btrfs 分区会丢失信息:打开用于写入的文件将其内容替换为零(文件大小或多或少保持不变)。我使用同步,我不希望这些假文件传播:我需要一种方法来识别它们,以便我可以从备份中获取它们。

l0b*_*0b0 10

你可以grep为?使用 Perl 正则表达式模式的字符:

$ echo -ne "\0\0" > nul.bin
$ echo -ne "\0x\0" > non-nul.bin
$ grep -P "[^\0]" *.bin
Binary file non-nul.bin matches
Run Code Online (Sandbox Code Playgroud)

所以你可以使用这个:

for path in *.foo
do
    grep -P "[^\0]" "$path" || echo "$path"
done
Run Code Online (Sandbox Code Playgroud)

  • @StéphaneChazelas OP 确实说过“忽略行尾字符”。所以任何只包含 `\0` 和 `\n` 字符(甚至是零)的文件都是匹配的。 (2认同)

Tho*_*hor 6

我同意 D_Bye 关于找到问题根源的说法。

无论如何检查文件是否只包含\0和/或\n您可以使用tr

<file tr -d '\0\n' | wc -c
Run Code Online (Sandbox Code Playgroud)

对于空/换行符和空文件,它返回 0。

  • `tr -d '\0\n'` 解决了换行问题,然后只留下输出中列出的空文件的问题(?)...它确实处理每个文件的每个字节(可能或可能不是问题)+1 (2认同)

Chr*_*own 5

这是一个可以做到这一点的小Python程序:

import sys

def only_contains_nulls(fobj, chunk_size=1024):
    first = True
    while True:
        data = fobj.read(chunk_size)
        if not data:
            if first:
                return 1  # No data
            else:
                return 0
        if data.strip("\0"):
            return 1
        first = False

if __name__ == '__main__':
    with open(sys.argv[1]) as f:
        sys.exit(only_contains_nulls(f))
Run Code Online (Sandbox Code Playgroud)

并在行动中:

$ printf '\0\0\0' > file
$ ./onlynulls file && echo "Only nulls" || echo "Non-null characters"
Only nulls
$ printf a >> file
$ ./onlynulls file && echo "Only nulls" || echo "Non-null characters"
Non-null characters
Run Code Online (Sandbox Code Playgroud)

您可以使用 find -execxargs、 GNUparallel和类似程序检查多个文件。或者,这将打印需要处理的文件名:

$ printf '\0\0\0' > file
$ ./onlynulls file && echo "Only nulls" || echo "Non-null characters"
Only nulls
$ printf a >> file
$ ./onlynulls file && echo "Only nulls" || echo "Non-null characters"
Non-null characters
Run Code Online (Sandbox Code Playgroud)

请记住,如果您要将其输出传递给另一个程序,文件名可以包含换行符,因此您应该以不同的方式对其进行分隔(适当地使用\0)。

如果您有很多文件,最好使用并行处理选项,因为它一次只能读取一个文件。

  • 请注意,此答案会错误识别零长度文件(例如:“/etc/nologin”、“~/.hushlogin”、“.nomedia”等)。 (2认同)

Sté*_*las 5

我怀疑这些文件是稀疏的,也就是说它们没有分配给它们的任何磁盘空间,它们只是指定了一个文件大小(du会为它们报告 0)。

在这种情况下,使用 GNU find,您可以执行以下操作(假设没有文件路径包含换行符):

find . -type f -size +0 -printf '%b:%p\n' | grep '^0:' | cut -d: -f2-
Run Code Online (Sandbox Code Playgroud)