Find arcana: can’t get pipe to work in -exec line

findpipescripting

How do I pipe the results of a find through a sed to xform the stream, and then use that transformed stream as one of two arguments to a script? IE:

find turns up file1.tiff (among others)
sed transforms file1.tiff –> file1.jpg
a command is executed using both of these arguments: convert file1.tiff file1.jpg

I've tried this a number of ways and can't get it. Here's one attempt that gives the flavor:

find ./out -regex ".*_p[bg]_.*tiff" -exec echo "Processing {}" \; -exec convert {} `echo {} | sed s/tiff/jpg/` \;

I should just give up and write a Python script to do each of these pieces separately, but I'm finally trying to learn UNIX tools and now am obsessed. Help!

Best Answer

I'm not sure you can have a pipe inside -exec. find -exec echo {} \| sed s/tiff/jpg \; doesn't seem to work.

If think your best option is to make a script to do the conversion, e.g.

convert_tiff_to_jpg:

#!/bin/bash
echo "Processing $1"
convert "$1" "${1/%tiff/jpg}"

and call it using find -exec like you had intended:

find ./out -regex ".*_p[bg]_.*tiff" -exec convert_tiff_to_jpg {} \;

There are a few ways to do it using find -print0 | xargs -0, but they are all quite ugly:

find ./out -regex ".*_p[bg]_.*tiff" -print0 |
while IFS= read -d $'\0' -r filename; do
    echo "Processing $filename"
    convert "$filename" "$(echo "$filename" | sed 's/tiff$/jpg/')"
done

or

find ./out -regex ".*_p[bg]_.*tiff" -print0 |
while IFS= read -d $'\0' -r filename; do
    echo "Processing $filename"
    convert "$filename" "${filename/%tiff/jpg}"
done

or

find ./out -regex ".*_p[bg]_.*tiff" -print0 |
    xargs -0 -I FILE bash -c 'F="FILE"; echo "$F" "${F/%tiff/jpg}"'

Note that I changed s/tiff/jpg to s/tiff$/jpg so that if tiff appears anywhere other than the end of the file name, it is not changed.

Related Question