Sign up ×
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 was using this little script to find malformed images:

find -name '*.jpg' -exec identify -format "%f\n" {} \; 2>errors.txt

It worked well enough, but now I need to modify it slightly. Instead of dumping the stderr to errors.txt, I want to dump the filename (%f) of the image that triggered the error. That is, I want a list of the malformed image files in errors.txt instead of a list error messages.

I tried adding || echo "%f" >> errors.txt to the -exec portion, but that didn't work. What would be the best way to do this?

share|improve this question

3 Answers 3

up vote 3 down vote accepted

This finds malformed images and stores their names in names.txt:

find -name '*.jpg' -exec bash -c 'identify "$1" &>/dev/null || echo "$1">>names.txt' none {} \;

How it works

  • find -name '*.jpg'

    This starts up find as usual.

  • -exec bash -c 'identify "$1" &>/dev/null || echo "$1" >names.txt' none {} \;

    This runs identify on each file and, if identify returns a non-zero error code, it echoes the file name to names.txt.

    bash -c '...' none {} causes a bash shell to run the command in the quotes with the file name in {} assigned to positional argument $1.

    For the curious, the string none is assigned to $0. Since we never use $0, the none is, in effect, a dummy placeholder.

Discussion

I tried adding || echo "%f" >> errors.txt to the -exec portion, but that didn't work. What would be the best way to do this?

The subtlety is that the || has to operate on the identify command. To that, we need to put identify in a shell such as by using bash -c as shown above.

share|improve this answer
    
Works great, and thanks for the explanation -- the 'bash' addition makes perfect sense. One minor thing: I had to change >names.txt to >>names.txt in order to get a list. –  Phll Apr 11 at 23:15
    
@Phll Glad it worked for you. Sorry about the > thing: the answer is now corrected. –  John1024 Apr 12 at 1:08

So you want like...

find . -name '*.jpg'  \
       ! -exec identify -silent {} \; \
       -print 2>/dev/null >errors.txt
share|improve this answer
find . -name '*.jpg' -exec sh -c '
  for file do
    if identify "$file"; then
      printf "%s\n" "$file" >&3
    else
      printf "%s\n" "$file" >&4
    fi
  done' sh {} + 3> good 4> bad > /dev/null 2>&1
share|improve this answer

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.