Take the 2-minute tour ×
Unix & Linux Stack Exchange is a question and answer site for users of Linux, FreeBSD and other Un*x-like operating systems.. It's 100% free, no registration required.

I've got a program that's behaving badly and has created a number of files with only a few non-printing characters. If I were to cat the files, I see nothing (since they are non-printing chars). However, these files will not show up if I use something like -empty or -size 0 with the find command.

Does anyone know of a way to search for files containing only non-printing characters?

share|improve this question
add comment

2 Answers 2

up vote 7 down vote accepted

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
share|improve this answer
    
Thanks, exactly what I needed! –  Joshc1107 Mar 5 '12 at 21:14
1  
Note: grep -L '[[:print:]]' -- * also lists empty files (having size of 0 bytes) -- this might or might not be desirable. Technically they don't contain NPSs. –  mindas Jun 18 '13 at 14:16
add comment

Your best bet is probably to use file. Try this:

find . -type f -exec file {} + | grep ": data"

Now, this won't catch files that randomly happen to have the right magic number at the start, but it's quite likely most other methods would miss them anyway.

Other ways to find these files:

  • Last modified time: find -mmin 5 = 5 mins ago
  • Size, not necessarily zero: find -size -4k = less than 4096 Bytes
share|improve this answer
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.