I ran into a situation that I don't really understand. I have a bunch of backup files in a recursive structure of which I want to calculate the md5. When I add some additional file extensions the process exits (exit code 0) without yielding any output.

find . -type f -iname "*.3gp" -o -iname "*.avi" -o -iname "*.mov" -o -iname "*.mp4" -print0 | xargs -0 md5sum
find . -type f -iname "*.3gp" -o -iname "*.avi" -o -iname "*.mov" -o -iname "*.mp4" -o -iname "*.mpg" -print0 | xargs -0 md5sum

The first one works fine, the second one doesn't yield any output. I've even tried it in a directory where there are no mpg files, same behavior.

Is there a limit on the number of arguments to find? I am running OSX and I installed md5sum from Macports.

Extra information

There seems to be something odd with the pipe and I'm inclined to blame the filenames. Further investigation in another folder shows me that the find command seems to work and there are 129 video files, 1 of which is .mpg. When I try the find+md5sum it returns after only 1 file. I ran a similar command in other folder that only contains pictures and it worked fine (found 80k files, yield 80k hashes).

Pictures@2006$ find . -type f -iname "*.3gp" -o -iname "*.avi" -o -iname "*.mov" -o -iname "*.mp4" | wc -l
Pictures@2006$ find . -type f -iname "*.3gp" -o -iname "*.avi" -o -iname "*.mov" -o -iname "*.mp4" -o -iname "*.mpg" | wc -l
Pictures@2006$ find . -type f -iname "*.3gp" -o -iname "*.avi" -o -iname "*.mov" -o -iname "*.mp4" -o -iname "*.mpg" -print0 | xargs -0 md5sum
 c21a78f2b2d5ca773b47647315ad91f8  ./pending photos/Video [%]/P007.MPG

I also noticed that the second filename to process contained punctuation, a plus sign and non-ascii characters. Is it possible that the error may be due to file naming? Is there any workaround?

/Esplai/+Nou/20060604 Dinar d'últim dia d'esplai[Barbacoa al torrent de l'Escaiola]/MVI_7702.AVI
  • What happens if you try each call to find by itself (without -print0 and without piping into md5sum)? – dhag Sep 11 '15 at 18:13

Let me first mention that -print0 is non standard and not the best solution. Better is to use "execplus", e.g.

find dir -type f -exec cmd {} +

Your main problem however is that the operators have precedence and your -print is "anded" with the last -name primary only.

So the right method is to put the -o red primaries in parenthesis:

find dir ( -name '*.x1' -o -name '*.x2' ) -exec cmd {} +

You may of course add more -o -type operators if you need.

  • Not sure what was the problem but using -exec solved it. – Josep Valls Sep 11 '15 at 20:41

If the operator expressions in a find command are not separated by -o (meaning or) or -a (and), there's an implicit -a between them. And -a binds more tightly than -o, so

find . -type f -iname "*.3gp" -o -iname "*.avi" -o -iname "*.mov" \
     -o -iname "*.mp4" -o -iname "*.mpg" -print0 

is going to be parsed as

find . '(' -type f -a -iname "*.3gp" ')' -o -iname "*.avi" -o -iname "*.mov" \
     -o -iname "*.mp4" -o '(' -iname "*.mpg" -a -print0 ')'

So the -print0 will only print files (and directories!) matching *.mpg. That's why, with this command, you're only processing one file rather than the 129 files you expect.

You can use parentheses (surrounded by quotes because they're also special to the shell) to change the grouping:

find . -type f '(' -iname "*.3gp" -o -iname "*.avi" -o -iname "*.mov" \
     -o -iname "*.mp4" -o -iname "*.mpg" ')' -print0 | xargs -0 md5sum
  • I did not know about the implied operator but it did not fix it. – Josep Valls Sep 11 '15 at 20:38

I think that you have a file in the current directory that matches the "*.mpg" wildcard, and expands to something that confuses find, e.g. ... -o iname A Movie about Birds.mpg. If you use single quotes, e.g. '*.mpg' rather than double quotes "*.mpg", wildcard expansion will not be done, and find will see *.mpg.

To see what is happening, either put an echo at the beginning (echo find ...), or pipe the result to | tr "\000" "\n"

  • The question mentions trying to run in a directory where no file matches *.mpg, and either single or double quotes should do the job equally, so the behavior is weird. It could still be interesting to know what a call to find with a single '*.mpg' pattern outputs. – dhag Sep 11 '15 at 18:06
  • Yeah, I already tried that. – Josep Valls Sep 11 '15 at 20:40
  • Tried what? Single quotes or rm *.mpg – waltinator Sep 11 '15 at 21:53

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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