Some of the filenames have spaces (problematic with xargs.
You just need to use the -print0
option for find
, and the -0
option for xargs
. They should really advertise these very much at the top of their man pages!
find -iname '*.pdf' -print0 | xargs -0 ...
just works. These options tell find
to separate found filenames with a zero byte instead of a newline character. Unlike spaces, newlines, colons, …, zero bytes are not allowed within file names, so this is a safe way to separate file names. -0
tells xargs
to expect zero bytes as dividers (and nothing else).
However, this is OS X, you got good shells going probably; so, no need for find
at all.
#!/usr/bin/zsh -
for pdffile in **/*.pdf(N-.) ; do
print -r -- "${pdffile}" # This is already problematic again. Your file names
# might contain newlines, spaces etc, so no easy way
# to tell where file name ends and page count starts
pdfinfo -- "${pdffile}" | grep Pages | awk '{print $2}'
done
Note the double quotation marks "
where you tried to use '
: Your code cannot work, because '
-encased string doesn't undergo variable expansion, so the string is passed as-is (including the dollar sign and variable name) to the program being called. Which is what you want for the awk
argument, because you need to pass $
, but not where you actually want to expand the content of your variable.
Note that fuzzy drawing's answer is right, you can absorb the grep into the awk
call. You should also make sure the regex is as precise as possible.
Let's also fix the "file names can contain spaces and newlines and numbers, so in my output I won't be able to tell where file names start and end" issue, by ourselves generating 0-delimited output:
#!/usr/bin/zsh
for pdffile in **/*.pdf(N-.) ; do
pages=$(pdfinfo -- "${pdffile}" | awk '/^Pages:/{print $2}')
printf '%s\0\%d\0' "${pdffile}" "${pages}"
done
(you could still have problems with PDF files whose Creator or Producer contains <newline>Pages:
, but at least, by using that strict regex above, we've minimised the risk).