Got less output with print0 option on find

find

I have read the man page and other references, but I am still confused by the behavior of find with -print0 option.

-print0      This primary always evaluates to true.  It prints the pathname of
             the current file to standard output, followed by an ASCII NUL
             character (character code 0).

First command:

$ find /some/path/ -iname "*intro*jpeg" -o -iname "*intro*jpg" 2> /dev/null
/some/path//asdf199Intro-5kqlw.jpeg
/some/path/199intro-2jjaj.JPEG
/some/path/199intro-3.jpg
/some/path/wuer199intro-4.JPG
/some/path/xbzf199INTRO-1.jpg

Second command:

$ find /some/path/ -iname "*intro*jpeg" -o -iname "*intro*jpg" 2> /dev/null -print0
/some/path/136intro-3.jpg/some/path/wuer136intro-4.JPG/some/path/xbzf136INTRO-1.jpg

I can see that the the filenames from the second command are null character separated, but why do I get 3 output as opposed to 5 above?

Best Answer

Your first example

 find /some/path/ -iname "*intro*jpeg" -o -iname "*intro*jpg"

is not equivalent to

 find /some/path/ -iname "*intro*jpeg" -o -iname "*intro*jpg" -print

It is equivalent to

 find /some/path/ \( -iname "*intro*jpeg" -o -iname "*intro*jpg" \) -print

When your expression contains any action other than -purge, the implicit print is no longer added. You want

find /some/path/ \( -iname "*intro*jpeg" -o -iname "*intro*jpg" \) -print0 2> /dev/null

The reason that you're only getting 3 filenames is that those are the ones matched by your second condition (the one that has an action). What you typed really means

find /some/path/ \( -iname "*intro*jpeg" \) -o \( -iname "*intro*jpg" -print0 \)

Which hopefully makes it clear why only 1 side prints anything.

Related Question