In short, what is happening here is that grep
is trying to interpret your file as Unicode data. The sequence 0xFF, 0xFE is a Byte Order Marker for UTF-16.
(In my testing, even other sequences involving two 0xFF's or two 0xFE's etc. would still not match the '[^\x00]'
regex, since even when trying to do UTF-8 these would be considered non-characters.)
Using a locale that doesn't use Unicode for character types should fix this, which you can accomplish by setting the LC_CTYPE environment variable. Use the C
locale to force ASCII encoding (so no Unicode enabled):
LC_CTYPE=C grep -RLP '[^\x00]' .
UPDATE: As pointed out by @steeldriver, grep still acts on a line-by-line basis, so files containing NUL bytes and newlines will still match.
@DavidFoerster's solution using grep's -z
does a good job of solving this problem, using the NUL bytes as separators does the trick.
Alternatively, I came up with a short Python 3 script (allzeroes.py
) to check whether the file's contents are all zeroes:
#!/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)
Which you can use in a find
to locate all matches recursively:
$ find . -type f -exec allzeroes.py {} \; -print
I hope that helps.