With GNU grep (and several other grep implementations), you can search for files that do not contain any printable character. The -L
option means to list the files that do not contain a match. [[:print:]]
(yes, there are two pairs of brackets) matches one printable character; the definition of printable character depends on your locale.
grep -L '[[:print:]]' -- *
Note that this includes empty files (as mindas pointed out).
To delete them all (review the grep
output first to make sure you're deleting the right files), assuming that the file names don't contain any newline character:
grep -L '[[:print:]]' -- * |
while IFS= read -r filename; do
if [ -f "$filename" ] && [ -s "$filename" ]; then
rm "$filename"
fi
done
or equivalently (note that this deletes empty files as well)
set +f; IFS='
' # split at newlines, turn off globbing
rm -- $(set -f; grep -L '[[:print:]]' -- *)
set -f; unset IFS
Note that the commands above will produce error messages if there are subdirectories in the current directory (because you'll be calling rm
on a directory — don't call rm -r
!). In zsh, you can use *(.L+0)
instead of *
to only match regular non-empty files, and you don't need to worry about special characters in file names (except newlines):
IFS=$'\n'
rm -- $(grep -L '[[:print:]]' -- *(.))
unset IFS
With only POSIX tools, grep -l '[[:print:]]' -- *
shows the files you want to keep (except empty files).
Or you can iterate over the files; this is clearer, and sure not to cause any trouble with special chacters (but skips dot files), but theoretically (but probably not measurably) slower.
for x in *; do
if [ -f "$x" ] && [ -s "$x" ] && ! grep -q '[[:print:]]' <"$x"; then
rm -- "$x"
fi
done