Bin Bash Terminal script to resize PNG/CR2/JPG ima

2019-09-06 15:14发布

问题:

I made a cool little script to take my massive photo collection of JPG/PNG/CR2 (raw files) and convert them into MacBook Pro Retina resolution of 2880px JPEGs.

This allows me to have all my pics on my computer while storing the giant originals on an external hard drive. Best of all the pics look fantastic because they're resized to my exact physical screen resolution 2880px wide!

You can easily adapt the script to your own needs...


OK so on to my question....

My pictures on my external hard drive are stored like this:

(Hard drive root)

Pictures

2013-05 Wedding in Vermont

img_0001.jpg

img_0002.jpg

2014-10 Las Vegas Trip

img_0001.cr2

img_0002.cr2

...

Right now the script OVERWRITES the original files... so I always need to make a complete copy of all my pictures to a 2nd drive and then run the script. Is there an easy way to make the script re-create the entire directory structure and write the new files out to a new folder/drive while maintaining the directory structure?

THANKS FOR YOUR HELP!

##################################
#!/bin/bash - resize2880px.sh (It's for Mac OS X computers)
# By Jason Fox of GetFoxy.com 2014 - hit me at jfox {at} foxnv.com if you have questions
# This script converts all PNG/JPG/CR2 files to JPG at a max resolution of 2880px (saving tons of space in the process).
# run it like this:
# 0. Save this script in your Documents Folder as resize2880px.sh
# 1. Open Terminal and CD into the directory of pictures to shrink
# 2. paste in:  find . -type f \( -iname "*.png" -o -iname "*.jpg" -o -iname "*.cr2" \) -exec sh ~/Documents/resize2880px.sh {} \;
# 3. If you have the awesome JPEGMini app... use it now to further save space! ;)

#the sizes to convert to
width=2880                                                                              
height=2880

#theFile given in input   
theFile=$1
echo ""
echo "$theFile"

#using sips to retrieve the width & height            
#size[0] = width
#size[1] = height
size=($(sips -g pixelWidth -g pixelHeight "$theFile" | grep -o '[0-9]*$'))                     

if [[ ${size[0]} -le $width && ${size[1]} -le $height ]];
    then echo "Width = ${size[0]} & Height = ${size[1]} SO... W<=$width H<=$height - no resize - just JPG convert"
    sips -s format jpeg "$theFile" --out "$theFile-t2880px.jpg"
elif [[ ${size[0]} -gt $width && ${size[1]} -le $height ]];
    then echo "Width = ${size[0]} & Height = ${size[1]} SO... W>$width H<=$height - Run SIPS $width JPG conversion"
    sips -Z 2880 -s format jpeg "$theFile" --out "$theFile-t2880px.jpg"
elif [[ ${size[0]} -le $width && ${size[1]} -gt $height ]];
    then echo "Width = ${size[0]} & Height = ${size[1]} SO... W<=$width H>$height - Run SIPS $width JPG conversion"
    sips -Z 2880 -s format jpeg "$theFile" --out "$theFile-t2880px.jpg"
elif [[ ${size[0]} -gt $width && ${size[1]} -gt $height ]];
    then echo "Width = ${size[0]} & Height = ${size[1]} SO... W>$width H>=$height - Run SIPS $width JPG conversion"
    sips -Z 2880 -s format jpeg "$theFile" --out "$theFile-t2880px.jpg"
else echo "Something is wrong."
fi

# Determine number of file system blocks used to store the original and new files
origfilesize=$(ls -s "$theFile" | awk '{print $1}')
newfilesize=$(ls -s "$theFile-t2880px.jpg" | awk '{print $1}')

if [[ $origfilesize -le $newfilesize ]];
    then echo "$origfilesize is less than or equal to $newfilesize - no space saved so deleting the new file"
    rm "$theFile-t2880px.jpg"
else
    echo "$origfilesize is greater than $newfilesize - deleting original file"
    rm "$theFile"   
fi

回答1:

Sure. Either set a variable in the script at the top, or pass in a new parameter that says where the new tree structure is to be created. Or do a mixture, and set a default new root directory but allow the user to overwrite it with a second parameter on the command line like this:

newroot=${2:-~/Desktop/resized}

Then use dirname to get the name of the directory that each input image is in, like this:

dir=$(dirname "/users/bozo/tmp/image.jpg")

that will give you

/users/bozo/tmp

now put the new directory path on the front

newpath="$newroot/$dir"

and make it, including all intervening folders and ignoring errors with

mkdir -p "$newpath" 2> /dev/null

and change your commands to output like this

 file=$(basename "input image path")
 sips ... --out "$newpath/$file"


回答2:

Here is the completed script! :)

##################################
#!/bin/bash - resize2880px.sh (It's for Mac OS X v10.6+ computers - Tested on v10.10 Yosemite)
# By Jason Fox of GetFoxy.com 2014 - hit me at jfox {at} foxnv.com if you have questions
# This script converts all PNG/JPG/CR2 files to JPG at a max resolution of 2880px (saving tons of space).
# run it like this:
# 0. Save this script in your Documents Folder as resize2880px.sh
# 1. Open Terminal and CD into the directory of pictures to shrink
# 2. paste in:  find . -type f \( -iname "*.png" -o -iname "*.jpg" -o -iname "*.cr2" \) -exec sh ~/Documents/resize2880px.sh {} \;
# 3. If you have the awesome JPEGMini app... use it to further save space! ;)

#Define the output folder
outputfolder=~/Desktop/2880px

#the sizes to convert to (max pixels)
width=2880                                                                              
height=2880

theFile=$1
echo ""

dir=$(dirname "$theFile")
newpath=$outputfolder/$dir/
echo $theFile will move to $newpath
mkdir -p "$newpath" 

#using sips to retrieve the width & height            
#size[0] = width
#size[1] = height
size=($(sips -g pixelWidth -g pixelHeight "$theFile" | grep -o '[0-9]*$'))                     

if [[ ${size[0]} -le $width && ${size[1]} -le $height ]];
    then echo "Width = ${size[0]} & Height = ${size[1]} SO... W<=$width H<=$height - no resize - just JPG convert"
    sips -s format jpeg "$theFile" --out "$outputfolder/$theFile-t2880px.jpg"
elif [[ ${size[0]} -gt $width && ${size[1]} -le $height ]];
    then echo "Width = ${size[0]} & Height = ${size[1]} SO... W>$width H<=$height - Run SIPS $width JPG conversion"
    sips -Z 2880 -s format jpeg "$theFile" --out "$outputfolder/$theFile-t2880px.jpg"
elif [[ ${size[0]} -le $width && ${size[1]} -gt $height ]];
    then echo "Width = ${size[0]} & Height = ${size[1]} SO... W<=$width H>$height - Run SIPS $width JPG conversion"
    sips -Z 2880 -s format jpeg "$theFile" --out "$outputfolder/$theFile-t2880px.jpg"
elif [[ ${size[0]} -gt $width && ${size[1]} -gt $height ]];
    then echo "Width = ${size[0]} & Height = ${size[1]} SO... W>$width H>=$height - Run SIPS $width JPG conversion"
    sips -Z 2880 -s format jpeg "$theFile" --out "$outputfolder/$theFile-t2880px.jpg"
else echo "Something is wrong."
fi

# Determine number of file system blocks used to store the original and new files
origfilesize=$(ls -s "$theFile" | awk '{print $1}')
newfilesize=$(ls -s "$outputfolder/$theFile-t2880px.jpg" | awk '{print $1}')

# File Size comparison (make sure we're saving space)
if [[ $origfilesize -lt $newfilesize ]];
    then echo "$origfilesize is less than to $newfilesize - delete new file - use original file instead"
    rm "$outputfolder/$theFile-t2880px.jpg"
    cp "$theFile" "$outputfolder/$theFile"
fi

Thanks for the help Mark Setchell!