2

I am able to use ImageMagick to create a thumbnail of the first page of a PDF using:

convert -thumbnail x80 95.pdf[0] thumb_95.png

This works fine and generates a thumb_95.png file.

I have tried several permutations of "find" using xargs but I can't get a combo working that will create the thumbnails in the folders along with the source PDFs.

The PDFs are in folders named with UUIDs, e.g.:

/511017a7-67fc-4897-80c1-0d42ac100b68/415.pdf
/511015bc-e0a8-4ab7-ba29-0ce9ac100b68/122.pdf

My required result would be:

/511017a7-67fc-4897-80c1-0d42ac100b68/415.pdf
/511017a7-67fc-4897-80c1-0d42ac100b68/thumb_415.png
/511015bc-e0a8-4ab7-ba29-0ce9ac100b68/122.pdf
/511015bc-e0a8-4ab7-ba29-0ce9ac100b68/thumb_122.png

Any help on the best ways to get this conversion to happen for all *.pdf recursively would be much appreciated!

1

3 Answers 3

1

The tricky part is to not have a filename of the form testfile.pdf.png as the output. Years ago I had the same problem and solved it with this helper script (adapted a bit):

#!/bin/bash 
SRCFRM=pdf
TGTFRM=png
FILE=$1

NEWFILE=$(echo $FILE | sed "s:$SRCFRM\$:$TGTFRM:")
convert -thumbnail x80 $FILE[0] $NEWFILE

Store it somewhere, e.g. in your home dir, then use it like this:

find /path -name '*.pdf' -exec /path/to/converthelper.sh {} \;
1

You want to

  • Recurse into all PDFs:

    1. Enable globstar, with shopt -s globstar.
    2. Use it to generate a list of all the *.pdf files under the current directory: **/*.pdf
    3. Create a loop that iterates over said files:

      for filename in **/*.pdf
      do
          something
      done
      
  • Now, you want to do something on the files: something is convert -thumbnail x80 95.pdf[0] thumb_95.png. There are several ways: I usually use basename, in this case you would need $(dirname $filename)/$(basename $filename .pdf).png, but another interesting (and simpler) approach is to use bash's string manipulation tools:

    1. Remove .pdf from the end of the filename: ${filename%.pdf}
    2. Add .png: ${filename%.pdf}.png

Finally, we can glue it all together (don't forget that this requires globstar, shopt -s globstar):

for filename in **/*.pdf
do
    convert -thumbnail x80 $filename[0] ${filename%.pdf}.png
done
0

Try this:

find /source/directory -name "*.pdf" -exec \ sh -c 'convert -thumbnail x80 {} $(dirname {})/thumb_$(basename {})' \;

I had to modify it slightly to:

find /source/directory -name "*.pdf" -exec \ sh -c 'convert -thumbnail x80 {} $(dirname {})/thumb_$(basename {} .pdf)'.png \;

To have basename strip the filextension and then append .png.

Thanks to all answers. This one worked well for me!

3
  • I needed to modify it to: find /source/directory -name "*.pdf" -exec \ sh -c 'convert -thumbnail x80 {} $(dirname {})/thumb_$(basename {} .pdf)'.png \; to have basename strip the fileext. Thanks to all answers this one worked best for me!
    – fibble
    Feb 6, 2013 at 15:53
  • Exercise to the reader: what happens if there's a file called $(rm -rf /).pdf somewhere in there. Feb 6, 2013 at 16:08
  • @StephaneChazelas: Good point. I had to originally add "sh -c..." to get the filename properly passed to the basename / dirname commands, but that opened up this security hole. If you are doing this on an untrusted directory, you can replace {} with '\''{}'\'', however you run into the same issue if a file is named '$(evil_command)'. Not sure of a correct way to close this one. Feb 6, 2013 at 17:48

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .