Reputation: 21
I have the following 2 scripts, that recursively convert folders of images to pdf's for my wifes japanese manga kindle using find and Imagemagick convert:
#!/bin/bash
_d="$(pwd)"
echo "$_d"
find . -type d -exec echo "Will convert in the following order: {}" \;
find . -type d -exec echo "Converting: '{}'" \; -exec convert '{}/*.jpg' "$_d/{}.pdf" \;
and the same for PNG
#!/bin/bash
_d="$(pwd)"
echo "$_d"
find . -type d -exec echo "Will convert in the following order: {}" \;
find . -type d -exec echo "Converting: '{}'" \; -exec convert '{}/*.png' "$_d/{}.pdf" \;
Unfortunately I am not able make one universal script that works for all image formats. How do I make one script that works for both ? I would also need JPG,PNG as well as jpeg,JPEG
Thx in advance
Upvotes: 1
Views: 490
Reputation: 21
@shawn Your solution works, just as I stated in the comments, I am to stupid to name the resulting pdf properly (folder name) and save in the script caller directory. Nevertheless, it solves my case insensitive jpg, jpeg, png problems just fine. Here is shawns solution:
#!/bin/bash
# enable recursive globs
shopt -s globstar nocaseglob extglob
for dir in **/*/; do
printf "Converting (jpg|jpeg|png) in %s\n" "$dir"
convert "$dir"/*.@(jpg|jpeg|png) "$dir/out.pdf"
done
@jhnc Your solution works out of the box, it does exactly what I intended, and I really like calling functions, or even standalone scripts to increase complexity. One drawback is, that I can not Ctrl-c the process, because it is thereby threaded, or runs in a subshell ? I think you were missing an exit statement at the end of the function, it never stopped.
#!/bin/bash
do_convert()(
shopt -s nullglob
for dir in "$@"; do
files=("$dir"/*.{jpg,JPG,png,PNG,jpeg,JPEG})
if [[ -z $files ]]; then
echo 1>&2 "no suitable files in $dir"
continue
fi
echo "Converting $dir"
convert "${files[@]}" "$dir.pdf"
done
exit
)
export -f do_convert
pwd
echo "Will convert in the following order:"
find . -type d
# find . -type d -exec bash -c 'do_convert {}' \;
find . -type d -exec bash -c 'do_convert "$@"' -- {} \+
@ everyone else, it's already after midnight again, I guess this is a trivial question for you guys, and I am very grateful for your ALL your answers, I didn't have the time to try everything.
I find linux bash very challenging.
Upvotes: 1
Reputation: 23784
how about a one-liner
find -name \*.jpg -or -name \*.png | xargs -I xxx echo "xxx =>" xxx.pdf
find -name \*.jpg -or -name \*.png | xargs -I xxx echo xxx xxx.pdf
help
-name
match name-or
logical or => both jpg and pngxargs
map input into a name to execute a command on-I
select a name, it is like {}
in fileNOTE
$(pwd)
which is a command substitution you can use variable $PWD
xxx
maps into a name and xxx.pdf
still has the matched extension found by find
. which means filename.png
becomes filename.png.pdf
. If this is not desired, you can sed
itconvert
command in parallel you can use -P 0
with xargs
-- see xargs --help
With sed
to remove extensions
find -name \*.jpg -or -name \*.png | sed 's/.\(png\|jpg\)$//g' | xargs -I xxx echo "xxx =>" xxx.pdf
Upvotes: 1
Reputation: 1639
A lot of ways to skin this cat. My thought is:
for F in `find . -type f -print`
do
TYPE=`file -n --mime-type $F`
if [ "$TYPE" = image/png ]
then
## do png conversion here
elif [ "$TYPE" = image/jpg ]
then
## do jpg conversion here
fi
done
Upvotes: -2
Reputation: 52344
I wouldn't use find
at all, just a loop:
#!/use/bin/env bash
# enable recursive globs
shopt -s globstar
for dir in **/*/; do
printf "Converting jpgs in %s\n" "$dir"
convert "$dir"/*.jpg "$dir/out.pdf"
done
If you want to combine .jpg and .JPG in the same pdf, add nocaseglob
to the shopt
line. Add .jpeg to the mix? Add extglob
and change "$dir"/*.jpg
to "$dir"/*.@(jpg|jpeg)
Upvotes: 2
Reputation: 16662
You can do more complicated actions if you turn the find exec into a bash function (or even a standalone script).
#!/bin/bash
do_convert()(
shopt -s nullglob
for dir in "$@"; do
files=("$dir"/*.{jpg,JPG,PNG,jpeg,JPEG})
if [[ -z $files ]]; then
echo 1>&2 "no suitable files in $dir"
continue
fi
echo "Converting $dir"
convert "${files[@]}" "$dir.pdf"
done
)
export -f do_convert
pwd
echo "Will convert in the following order:"
find . -type d
# find . -type d -exec bash -c 'do_convert {}' \;
find . -type d -exec bash -c 'do_convert "$@"' -- {} \+
nullglob
makes *.xyz
return nothing if there is no match, instead of returning the original string unchangedp/*.{a,b,c}
expands into p/*.a
p/*.b
p/*.c
before the *
are expandedx()(...)
instead of the more normal x(){...}
uses a subshell so we don't have to remember to unset nullglob
again or clean up any variable definitionsexport -f x
makes function x
available in subshellsbash
(probably doesn't save a great deal in this particular case)Upvotes: 1