1

I'm trying to do a batch imagemagick conversion on all tiffs in directories.

The structure of the directories looks like:

test    
    123
       456
          image.tif

    256
       857
          anotherimage.tif

I'm trying to use find to locate all the images, and then pass those into xargs for imagemagick to convert to jp2. The output filename would be a combination of the granparent and parent directory names, so in the example above, image.tif would be converted to 123456.jp2.

I've got the find working ok, but just can't get the correct combination of imagemagick and find params to achieve what I need. Here's the find with xargs. The {grandparentdir} and {parentdir} are placeholders for the bit I'm missing!

find /var/tmp/test -type f \( -name "*.tif" -o -name "*.TIF" -o -name "*.tiff" -o -name "*.TIFF" \) -mtime -1 | xargs convert -quality 100 \var\tmp\test\{granparentdir}{parentdir}.jp2"
Goat Karma
  • 123
  • 5

2 Answers2

2

Run a shell from find -exec and manipulate the paths there:

find /var/tmp/test -type f \
   \( -name "*.tif" -o -name "*.TIF" -o -name "*.tiff" -o -name "*.TIFF" \) \
   -mtime -1 \
   -exec sh -c '
      for f do
         parent="$(basename "$(dirname "$f")")"
         grandparent="$(basename "$(dirname "$(dirname "$f")")")"
         printf "%s\n" "$grandparent$parent.jp2"
         # convert   -- whatever arguments you want
      done
   ' sh-find {} +

I used dirname and basename in a non-optimal way. You can use shell parameter expansion instead (${f%/*} etc.) and e.g. realpath if needed.

The point is you run a shell and you can do anything in it.

In my example the whole shell code is single-quoted (this is because any expansion by the outer shell is potentially unsafe, the inner shell will parse the result). If you need single-quotes inside the code then proper quoting will get somewhat complicated. In this case instead of -exec sh -c '…' sh-find {} + consider -exec sh ./script {} + where script is a file containing the code. Inside the file you quote like in any other shell script.

If you need Bash, use -exec bash. Use whatever shell you need. Or something else. If you need Python, use -exec python. This approach is quite powerful.


More information:

Kamil Maciorowski
  • 69,815
  • 22
  • 136
  • 202
1

This might be helpful for others. I ended up splitting the command into two:

  1. transform the files first
  2. Move/rename afterwards

1. Transform using mogrify

find /var/tmp/test -type f -not -name "*.thumb*" -not -name "*.500x500*" \( -name "*.jpg" -o -name "*.JPG" -o -name "*.png" -o -name "*.PNG" -o -name "*.tif" -o -name "*.TIF" -o -name "*.tiff" -o -name "*.TIFF" -o -name "*.bmp" -o -name "*.BMP" \) | xargs mogrify -format jp2

2.Rename and move the file to a location of my choice

find /var/tmp/test -type f -name "*.jp2" -execdir bash -c \ 'old="{}"; new="$(cd ..; basename -- "$PWD")$(basename -- "$PWD").jp2"; mv "$old" /var/tmp/test/"$new"' - {} \;
Goat Karma
  • 123
  • 5