Stalin Kay
Stalin Kay

Reputation: 607

How to use xargs to replace 2 arguments

I would like to write a script to convert svg files in a directory to png using svgexport cli

svgexport input.svg input.jpg

How can I use find and xargs -I {} to find and print out the svg files using the following:

find . -iname -0 "*.svg" | xargs -I {} svgexport {} ???

How can I fill-in the second argument by using the first argument and replacing .svg with .jpg?

Upvotes: 9

Views: 5107

Answers (5)

redneb
redneb

Reputation: 23850

I think it's best to do this with a while loop:

find . -iname "*.svg" -print0 |
    while IFS= read -r -d '' file; do
        svgexport "$file" "${file%.svg}.jpg"
    done

Upvotes: 4

jlliagre
jlliagre

Reputation: 30813

You can avoid xargs when you use find. It already provides the same feature a simpler way (-exec with + terminator):

find . -iname "*.svg" -exec \
    bash -c 'for i do svgexport "$i" "${i::-3}jpg";done' bash {} +

Should you don't want to recurse in subdirectories:

find . -maxdepth 1 -iname "*.svg" -exec \
    bash -c 'for i do svgexport "$i" "${i::-3}jpg";done' bash {} +

but in that case, find is not necessary either:

for i in *.[sS][vV][gG]; do svgexport "$i" "${i::-3}jpg"; done

If the suffix is always in lowercase, this can be slightly simplified:

for i in *.svg; do svgexport "$i" "${i%svg}jpg"; done

If your bash version doesn't support ${i::-3}, you can use the portable {i%???} instead.

Should you want to avoid the bash and find GNUisms, here is a POSIX way to achieve the recursive processing:

find . -name "*.[Ss][Vv][Gg]" -exec \
    sh -c 'for i do svgexport "$i" "${i%???}jpg";done' sh {} +

and another for the non recursive one:

for i in *.svg; do svgexport "$i" "${i%???}jpg"; done

Upvotes: 2

Orsiris de Jong
Orsiris de Jong

Reputation: 3016

Easy:

find . -iname "*.svg" -print0 | xargs -0 -I \
bash -c 'export file="{}";  svgexport "$file" "${file%.*}.jpg"'

Add -print0 to find and -0 to xargs to deal with special filenames. ${file%.*} removes all chars after the last dot, so it will remove ".svg" and you can add the new file extension.

Upvotes: 1

anubhava
anubhava

Reputation: 785058

You can use bash -c in xargs and use BASH's string replacement:

find . -name "*.svg" -print0 |
xargs -0 -I {} bash -c 'svgexport "$1" "${1%.svg}.jpg"' - {}

Upvotes: 6

Mark Setchell
Mark Setchell

Reputation: 207425

Do them all simply, and faster, in parallel with GNU Parallel

parallel --dry-run svgexport {} {.}.jpg ::: *.svg

Remove the --dry-run if you like what it shows you and run it again to actually process the files.

Upvotes: 5

Related Questions