This one-liner is the most efficient way to find 100% nul files using GNU find
, xargs
, and grep
(assuming the latter is built with PCRE support):
find . -type f -size +0 -readable -print0 |
LC_ALL=C xargs -r0 grep -LP "[^\x00]" --
The advantages of this method over other provided answers are:
- non-sparse files are included in the search.
- non-readable files aren't passed to grep, avoiding
Permission denied
warnings.
grep
will stop reading data from files after finding any non-nul byte (LC_ALL=C
is used to make sure each byte is interpreted as a character).
- empty files (zero bytes) are not included in the results.
- fewer
grep
processes efficiently check multiple files.
- paths containing newlines or starting with
-
are handled correctly.
- works on most embedded systems that lack Python/Perl.
Passing the -Z
option to grep
and using xargs -r0 ...
allows further actions to be performed on the 100% nul files (eg: cleanup):
find . -type f -size +0 -readable -print0 |
LC_ALL=C xargs -0 grep -ZLP "[^\x00]" -- |
xargs -r0 rm --
I also recommend using the find
options -P
to avoid following symlinks, and -xdev
to avoid traversing filesystems (eg: remote mounts, device trees, bind mounts, etc).
For ignoring the line end character(s), the following variant should work (though I don't think this is such a good idea):
find . -type f -size +0 -readable -print0 |
LC_ALL=C xargs -r0 grep -LP "[^\x00\r\n]" --
Putting it all together, including removing the unwanted files (100% nul / newline characters) to prevent them from being backed up:
find -P . -xdev -type f -size +0 -readable -print0 |
LC_ALL=C xargs -0 grep -ZLP "[^\x00\r\n]" -- |
xargs -0 rm --
I don't recommend including empty files (zero bytes), they often exist for very specific purposes.
-v
option to grep: filter out all files that have any byte 1 to 255.