Using Ubuntu 22.04. I have a Bash command that produces a list of GIF files
$ <command>
file1.gif
file3.gif
file12.gif
...
I would like to convert the files in this output to PNG files using the ImageMagick convert
command. For a single file, the command would look something like
convert "<basename>.gif" "<basename>.png"
Since I have many files, though, I want to pipe the output of the original command into the convert
command, like
$ <command> | convert "<???>" "[<???>%.gif].png"
where I’m attempting to use Bash’s features for removing the .gif
extension from input files and adding the .png
extension.
Ideally, I could capture the output of each line of <command>
as a variable and reference that variable in the convert
portion of the command, like
$ <command> | convert "$1" "[$1%.gif].png"
where $1
stands in for file1.gif
, file3.gif
, file12.gif
, etc. I’ve been searching for hours, and I can’t find anything similar to that ability, though.
This is a specific example of a general Bash problem of how to pipe to a command that has two inputs, which does not have an obvious solution because the "destination" of the pipe is ambiguous. I’ve also searched for solutions to that general problem, but fruitlessly.
Can this "one -> multiple" piping be done from the command line?
3
Answers
Consider a BashFAQ #1
while read
loop, using a process substitution to avoid the bugs described in BashFAQ #24.If you care more about portability than the bugs described behind the link, then you can pipe to the loop:
Not at a computer to test until tomorrow, but the ImageMagick suite can read its input filenames from a file preceded by
@
, so iffilelist.txt
contains 2 filenames, you can append the images side-by-side using:If you want to read filenames from ImageMagick‘s stdin, you can use:
But you want multiple output files, so you want
mogrify
, so you need:Or… completely different concept… you can get them all done in parallel with GNU Parallel and let it strip the GIF extension and replace it with PNG:
You can do that in Imagemagick as follows as an example. I have two images lena.jpg and zelda1.jpg and I want to convert them to GIFs.
The @- takes a list from stdin which in this case is just an echo of the file names. The +adjoin is needed to avoid having the image go into different frames of the GIF. (Remove the +adjoin if you want to make and animated GIF). With the +adjoin, you get one output per input. The -set filename:f stores the names from %t which excludes the suffix. They are then recalled in the output as %[filename:f]. Change f to anything you want or just keep f.
Note: the @- may need you to modify your policy.xml file to be able to use @.