Search code examples
bashgnu-parallel

Extract specific path component in GNU parallel


Given these files in in/,

$ find -type f | sort
./in/x/y/z1/i.jpg
./in/x/y/z2/i.jpg
./in/x/y/z3/i.jpg
./in/x/y/z4/i.jpg
./in/x/y/z5/i.jpg

I would like use GNU parallel to convert all JPEGs to PNGs, to create

./out/z1/png/i.png
./out/z2/png/i.png
./out/z3/png/i.png
./out/z4/png/i.png
./out/z5/png/i.png

My non-working solution so far, where <???> should be the zX path component from the input path:

find -type f | parallel "convert {} /path/to/out/<???>/png/{/.}.png"

In GNU parallel, how to extract the n-th path component from the input path? I.e. how do I get the zX part from ./in/x/y/zX/i.jpg?

Update: I do not want to export a function.


Solution

  • Use a perl expression replacement string

    find -type f | parallel 'echo convert {} /path/to/out/{= s:.*/([^/]*)/[^/]*:\1: =}/png/{/.}.png'
    

    prints

    convert ./in/x/y/z1/i.jpg /path/to/out/z1/png/i.png
    convert ./in/x/y/z2/i.jpg /path/to/out/z2/png/i.png
    convert ./in/x/y/z3/i.jpg /path/to/out/z3/png/i.png
    convert ./in/x/y/z4/i.jpg /path/to/out/z4/png/i.png
    convert ./in/x/y/z5/i.jpg /path/to/out/z5/png/i.png
    

    If this is what you want, then remove the echo.