Using a Shell Script to Batch Process an Image

Shell scripts can be created in TextEdit and run in the Terminal app. In this example, we'll create a script that takes a single image and produces multiple versions of that image by looping through a series of sizes. This script can be used again and again to reproduce the image series when changes are made to the original.

Video Transcript
When we talk about batch resizing images we're usually talking about taking a collection of images and resizing them all to be the same size or scale them down the same amount. But sometimes you're doing, kind of, the opposite. You're taking a single image and you want to produce multiple versions of it. App developers have to do this all the time to produce the icons in their apps. Sometimes you need to do it for other purposes as well. For screen shots and different things in projects.

So let's look at an example for a way to do it. But instead of using Automator or some batch processing tool inside of an image editing app like Photoshop or something we'll use the Terminal and create a shell script. A shell script is something that runs in the Terminal that's more than one line and it's a little program.

So here I've got in a folder a test image and I've got my script which is in a text file that I can open up in TextEdit. Here it is. It's pretty simple. When you write a shell script in TextEdit you it start off with the line that's the pound symbol or hash symbol, exclamation point, and then slash bin slash bash. This says that when this file is run as an executable it should be run using the bash shell, which is usually what you type commands in using the terminal.

Then I set a variable. Just two letters, FN, I use for the variable and I set it to TestImage which is the name of the file. In this case it's TestImage dot jpg. Now here's the tricky part. This is the part that you can't just do as a regular terminal command. I'm going to loop and go through a series of sizes. So I'm going to use for and then another variable calls SIZE in and then a whole series of numbers. 29, 40, 48, 50 all the way up to 1024. These are going to be the sizes for the images I'm going to generate. They happen to be the sizes you need when you create an app icon if you're an app developer. Then after for you need to follow it up with do and done. Between them you have the command.

The command is going to run the sips command which is something built in the terminal that you can use to resize images. You can just do it as a single line using a similar format just to process an image from one size to another. Dash Z means we want to resize it. Then the SIZE is going to take the value of the variable size. Put the dollar sign in front of it to indicate that. So the first time it runs this will be a 29. The second time it will be 40, etc.

Then with quotes around it we're going to use the value of the variable FN, so the test image, and we put these little brackets around it to make it clear what the variable is. We didn't need to do that here because we've got spaces around SIZE. Now we do dash dash out. So we're going to output it, not as the same file name not replacing the file, but we're going to use a different file name which is going to be the thing in-between the quotes here, the same name so TestImage, but also tag on the variable SIZE. So in other words instead of TestImage.jpg we'll end up with TestImage 29.jpg.

Then it's going to loop. It will do the same thing but the size is going to be 40. So you end up taking the image, resizing it to a 40 by 40 and it's a square image in this case so it makes it easy. Then you end up with a TestImage of 40.jpg. Then it will do 48 all the way to 1024.

So we'll close this and how do we run it? Well, if we're going to run it by launching terminal. The first thing we need to do is we need to get into this directory here. So we'll do cd, change directory, and I'm going to drag the folder here just as a quick way to type that name. So now we should be in there. I can check by using List Directory, ls, and we can see there is ProcessImage.txt and TestImage.jpg. So we are in the right place.

Now to run this I'm going to do./ which is just a good way to force it to, instead of accessing the file to actually run the file, and we'll do ProcessImage.txt. A lot of people like to rename the file .sh instead of .txt but it really doesn't matter. It's going to run it no matter what the extension is.
I'll hit Return and you can see it does a whole bunch of processing. Outputs for each time through the loop exactly what it's doing. I look now at the directory and I can see that it is now filled up with files that are that size. This was a 1024 by 1024. Actually this was a larger image. 4000 by 3000. So this is now 1024 by 768. So the maximum width was 1024. Then the other dimension, the height, follows suit. You have that all the way down to this one, the 29 by 21. So in the case of doing app icons, of course these are square images like I mentioned before, you would start off with the 1024 by 1024 and you would get a repeat of that and then one 512 by 512, 180 by 180, all the way down to 29 by 29. But since this is a non-square image, 4000 by 3000, you will just get the maximum dimension being that.

So this is an easy way to do it and the great thing about it is, for doing things like app icons and things, it's very common to change that image and then want to regenerate all of these. So here you can just delete them, or I believe it will just override the image if I would run it again. I could have it very easily, in terminal here, go ahead and recreate all those little images from this one big one.

Comments: 8 Responses to “Using a Shell Script to Batch Process an Image”

    Stephen
    2/8/18 @ 10:13 am

    Absolutely fascinating – so good to see a technical / programming tip every so often! More, please, Gary!

    Steven
    2/8/18 @ 12:07 pm

    Very nice!
    So you don’t have to make the file executable with chmod anymore (or did I miss that step)?

    2/8/18 @ 1:38 pm

    Steven: You only have to make it executable if you want to run it from the Finder. In this example, we are running it from the Terminal.

    Silvio
    2/9/18 @ 3:21 pm

    Thanks for these wonderful tutorials.
    A question.
    I did exactly as explained, but the terminal denies me permission:
    MacSilvio: Ridimensiona immagine silviomarcis $ ./ProcessaImmaginee.txt
    -bash: ./ProcessaImmagine.txt: Permission denied
    Naturally, I am logged in as a Director.
    I tried to put before the SUDO command but the result is the same.
    How do I solve?
    Thank you
    Translated from Italian with Google. Sorry

    2/9/18 @ 3:23 pm

    Silvio: Do you mean you are logged in as an “administrator?” If so, it should work. But perhaps you have something else going on that is preventing it. If you are feeling adventurous, look into using the chmod command to change the permissions on that file so it will run.

    Silvio
    2/10/18 @ 4:33 am

    Gary: You were right, I added the executable property to the file and it does not give me that error anymore. But another.”Warning: “Acitrezza.jpg” not a valid file – skipping
    Error 4: no file was specified”I tried with other files but the result is the same.This is the listing of the txt file:
    #! / Bin / bash
    FN = “Acitrezza”
    for SIZE in 29 40 48 50 57 58 60 72 75 76 80 87 100 114 120 144 152 167 180 512 1024
    do
    sips -Z $ SIZE “$ {FN} .jpg” –out “$ {FN} $ {SIZE} .jpg”
    done
    Thanks

    2/10/18 @ 8:01 am

    Silvio: It looks like you have all sorts of extra spaces in your code. There shouldn’t be any spaces after the $ characters and before the { brackets. There are also extras spaces in your first line too, which is probably why you couldn’t get the code to run in the first place. And make sure the quotes are all straight quotes, not curly ones, though that may have happened when you pasted it in the comments field.

    Silvio
    2/10/18 @ 9:01 am

    Gary: They were the quotes. Everything’s ok, it works.
    Thanks 👍

Leave a New Comment Related to "Using a Shell Script to Batch Process an Image"

:

:

:


0/500 (500 character limit -- please state your comment succinctly and do not try to get around this limit by posting two comments)