Get multiple extensions in a for loop for transforming jpg,JPG and jpeg files - bash

I want to convert all jpgs (independent from lower or upper case or jpeg extension) in my current directory to a 95% optimized one. However I do not get the files correctly in my for loop with JPG,jpg and jpeg files :/
#!/bin/bash
PIC=$(ls "$PWD"/*.{jpg,jpeg,JPG})
for i in $PIC
do
echo $i
# convert $i -quality 95 ${i%.*}_resaved.jpg
done

Try:
find -iname "*.jpg" -o -iname "*.jpeg" | while read f; do
echo "$f"
convert "$f" -quality 95 "${f%.*}_resaved.jpg"
done

Related

Changing all images in a directory and its sub-directories using a single ImageMagick command?

I have a directory with multi level sub-directories containing .jpg files that I want to change using ImageMagick.
To change a single file I do convert image0.jpg -resize x1000 -quality 82 small_image0.jpg
But how can I do the same but for all the jpgs in every directories, with a single command?
That is:
Apply -resize x1000 -quality 82 to every jpg in all of the directories.
Every output file should be in the same directory as its input file but with small_ prepended to the name.
With find and bash.
#!/usr/bin/env bash
path=("$#")
while IFS= read -ru9 -d '' pic; do
dirname=$(dirname "$pic")
basename=$(basename "$pic")
printf 'Converting %s to %s\n' "$pic" "$dirname/small_$basename"
convert "$pic" -resize x1000 -quality 82 "$dirname/small_$basename" || exit
done 9< <(find "${path[#]}" -type f -name '*.jpg' -print0)
Assuming you name your script myscript, execute it with the path to the pictures as the argument.
./myscript /path/to/pictures
Change /path/to/pictures with the correct path/directory, or add more path/directory separated by a space e.g. ./myscript path1 path2 anotherpath morepath
instead of just one directory.

Git Bash for loop through files

Okay, I am trying to loop through all images in a directory and do some compression on them. Here is my code.
#!/bin/bash
for f in *.jpeg; do
echo "Processing $f file..";
magick convert -quality 85% $f $f
done
And here is the output from it:
$ bash compress.sh Processing *.jpeg file.. convert: unable to open
image '*.jpeg': Invalid argument # error/blob.c/OpenBlob/3094.
convert: no images defined `*.jpeg' #
error/convert.c/ConvertImageCommand/3254.
The $f reference is actually the string "*.jpeg", which is definitely not correct.
Here is my folder structure.
I ended up doing this, which does the job.
#!/bin/bash
find ./images -name '*.jpg' | while read FILE; do
magick convert -quality 75% "$FILE" "$FILE"
done
You should lookup files with appropriate filename mask (directory and extension). Also there should be skip path if bash can't expand filename:
#!/bin/bash
IMAGE_PATH=`dirname ${BASH_SOURCE[0]}`/nature
for f in $IMAGE_PATH/*.jpg $IMAGE_PATH/*.jpeg; do
echo -n "Processing $f file... ";
if [ ! -r "$f" ]; then
echo "skip!";
continue;
fi;
magick convert -quality 85% "$f" "$f";
echo "done.";
done
PS: "$f" (with quotes) used for files with spaces in their names.
UPDATE: Add using script directory.

Bash convert resize recursively preserving filenames

Have images in subfolders that need to be limited in size (720 max width or 1100 max height). Their filenames must be preserved. Started with:
for img in *.jpg; do filename=${img%.*}; convert -resize 720x1100\> "$filename.jpg" "$filename.jpg"; done
which works within each directory, but have a lot of subfolders with these images. Tried find . -iname "*.jpg" -exec cat {} but it did not create a list as expected.
This also didn't work:
grep *.jpg | while read line ; do `for img in *.jpg; do filename=${img%.jpg}; convert -resize 720x1100\> "$filename.jpg" "$filename.jpg"`; done
Neither did this:
find . -iname '*jpg' -print0 | while IFS= read -r -d $'\0' line; do convert -resize 720x1100\> $line; done
which gives me error message "convert: no images defined." And then:
find . -iname '*.jpg' -print0 | xargs -0 -I{} convert -resize 720x1100\> {}
gives me the same error message.
It seems you're looking for simply this:
find /path/to/dir -name '*.jpg' -exec mogrify -resize 720x1100\> {} \;
In your examples, you strip the .jpg extension, and then you add it back. No need to strip at all, and that simplifies things a lot.
Also, convert filename filename is really the same as mogrify filename. mogrify is part of ImageMagick, it's useful for modifying files in-place, overwriting the original file. convert is useful for creating new files, preserving originals.
Since all of the subdirectories are two levels down, found this worked:
for img in **/*/*.jpg ; do filename=${img%.*}; convert -resize 720x1100\> "$filename.jpg" "$filename.jpg"; done
Thanks to #pjh for getting me started. This also worked:
shopt -s globstar ; for img in */*/*.jpg ; do filename=${img%.*}; convert -resize 720x1100\> "$filename.jpg" "$filename.jpg"; done
But I got the error message "-bash: shopt: globstar: invalid shell option name" but all of the images larger than specified were resized with filenames preserved.

bash batch image resize

How change this string:
find . -type f -name "*.jpg" | while read i; do convert "$i" -resize 50% "${i%%.jpg*}_tn.jpg"; done
to make tn_FILENAME.jpg files, not FILENAME_tn.jpg
Thank you!
find . -type f -name "*.jpg" | while read i; do [[ "${i##*/}" =~ ^tn_ ]] || convert "$i" -resize 50% "${i%/*}/tn_${i##*/}"; done
You mean like this?
${i%/*} is the filename stripped of everything following the last dash (so the dir in which the file is located).
/tn_ adds the tn_ prefix to the file, and
${i##*/} strips everything from the file before the last dash (so it's the filename).
Paste these three together and you get your result.

Batch resize and rename image files in subdirectories

I'm trying to resize and rename several hundred subdirectories of images. The files that I need to be changed:
End with A.jpg
Need to be resized down to 400x400
Renamed to A#2x.jpg
Example:
images/**/A6919994719A#2x.jpg
I got the resizing bit down in one directory. I'm having some trouble finding a way to rename just the end of the file, not the extension, and executing it through the subdirectories.
Any help would be appreciated.
#!/bin/bash
for i in $( ls *A.jpg); do convert -resize 400x400 $i
You can do this:
#!/bin/bash
find . -name "*A.jpg" | while read f
do
newname=${f/A.jpg/A#2.jpg}
echo convert "$f" -resize 400x400 "$newname"
done
Remove the word echo if it looks correct, and run only on files you have backed up.
You can also do it in a one-liner, if you really want to:
find . -name "*A.jpg" -exec bash -c 'old="$0";new=${old/A.jpg/A#2.jpg};echo convert "$old" -resize 400x400 "$new"' {} \;

Resources