Make some thumbnails real quick...

PSSSSTTT… Hey kid. Yeah, you over there. Wanna make some thumbnails?

⬆︎   That image up there is completely unrelated, although you could make a thumbnail of it if you wanted, I guess? No judgements…

What are thumbnails and why do I need to make them?

Barring the obvious jokes about Kenneth from 30 Rock and his reluctance to surrender his precious fingernails, you might wonder what thumbnails have to do with you. Well, say that you have a website and you have a folder full of images to go onto that website. What are you gonna do, put them all up at their original size?

HELL NO you aren’t. You’re not some kind of monster, are you? No, you’re gonna make smaller versions of your precious images so that your visitors can click on the one(s) that they want. Right? Right.

Thumbnails are just smaller versions of a larger image that you’re loading up to save a user from downloading giant images. Or, they can be used in a place where you wouldn’t necessarily want to show a whole image at full size. There’s a lot of reasons to use thumbnails, so I’m not going to try to outline all of them. Ask “The Google” about them if you’re not following at this point.

Things that you probably need to do this:

  • A computer with a command line that you can type things into
  • Some kind of code editor (Like Atom, VScode, Sublime Text, TextMate, etc)
  • ImageMagick
  • A folder of images

On a Mac? Don’t have any of this stuff installed already? Check out the script I have in this repo, which will pretty much do everything for you (short of actually creating the images that you want to convert.)

Let’s DO IT already

Now, this whole process is really pretty easy. You don’t need much to make this work. The only reason that I’m putting it here is because someone out there, some day, might be like “Well shit, I need to know how to make thumbnails and I’m not gonna check with those nerds over at Stack Overflow AGAIN. They’ll just make fun of me.” Not me buddy. I feel your pain.

Let’s start with the script itself:

#!/usr/bin/env bash


if [ ! -d "$output_dir" ]; then
  mkdir -p "$output_dir"

for notpornimages in $input_dir/*."{$exts}" ; do
  convert "$notpornimages" \
    -thumbnail 250x250^ \
    -gravity center \
    -extent 250x250 \
    -set filename:fname '%t_thumb' \

There’s not a whole lot to it, but being a somewhat “novice” at shell scripting (and the ImageMagick docs being ALL over the place), it took me awhile to get to this point. Hopefully what I’ve put together helps make sense of the whole thing.

Breaking it down

#!/usr/bin/env bash

This is your shebang. It tells the interpreter what kind of program you’re running. In our case, this is a bash script… so we’re specifying whichever bash executable appears in the users $PATH. If you want to use the specific version on your system, put the results of which bash from your terminal in here.

The variables


For the sake of this demo, we’re going to assume that you have a folder on your Desktop named Definitely_NOT_Porn. This variable just specifies the directory that has the images in it that we want to process. This is where you can substitute the path to your actual folder. The $HOME part is plopping in your home directory path. Feel free to change or take that out if you’re using the full path to your input directory.

So, for instance… for me, $HOME expands to /Users/pitman. (Check for yourself using echo $HOME on the command line.) So $HOME/Desktop/Definitely_NOT_Porn would really be like putting the full path of /Users/pitman/Desktop/Definitely_NOT_Porn in there.

Go ahead and leave off the trailing slash, as it’s already specified in the loop below.


This is a list of filetypes/extensions that you want the loop to process. Case matters here, as if you have a bunch of images with an uppercase .JPG as the filename, you want to specify that here, otherwise they’ll be skipped over. It’s ok to have extensions here that you don’t have filetypes for in your input directory, as the loop will just ignore them if there aren’t any files matching what we’re specifying here.


This is the directory where you want your processed thumbnails to go when the script is done doing it’s thing. (This directory will be created if it doesn’t already exist.)

The for loop

for notpornimages in $input_dir/*."{$exts}" ; do

Here’s where the magic happens. This is a for loop that takes everything in the directory (that we specified in the variables above) and does the thing that we tell it to do (inside of the loop) to each file. Let’s break that down real quick:

for ... in ... ; do

  • This is the basic syntax of saying that for each item in our directory, do the thing that we’ve specified below.


  • This is a name that we’re giving to the loop. This can be whatever you want, however you need to make sure that it’s the same as the $notpornimages inside of the loop if you change it.


  • This is just putting the variable of our input directory that we specified above into use. It lets the for tag know what directory it should be processing stuff from.


  • See, the / is in there acting as our trailing slash (that I told you earlier we didn’t want to specify in our $input_dir variable).
  • The * is wildcard matching all files in the directory. It’s just saying that we want to process everything in our $input_dir.
  • The "{$exts}" is our variable (for filename extenstions) that we set earlier. We’re using literal glob expansion here (with the quoted "{ }"), as we’re just passing the list of our wanted file extensions in, so the script knows what we want it to process.


  • Just a line to show that we’re done telling the loop what we want it to do.

Do the ImageMagick stuff

convert "$notpornimages" \
  -thumbnail 250x250^ \
  -gravity center \
  -extent 250x250 \
  -set filename:fname '%t_thumb' \


  • This one should be pretty self-explanatory, so I’ll let your imagination run with it. Get this… it CONVERTS stuff. This is us telling ImageMagick that we want to convert the files in our directory.

    It’s worth noting that when you’re using convert in a batch, it puts all of the images into memory. So if you’re processing a ton of images and are low on RAM, the script may run out of memory.


  • Our name that we gave the thing earlier. Needs to match up with what we specified at the start of the for loop.


  • So, these forward slashes at the end of each line is just so the script is more readable, and not just on one long line. It makes reading your long ass command easier.

    A backslash escapes the next character from being interpreted by the shell. If the next character is a newline, then the newline will not be interpreted as the end of the command by the shell. It effectively allows the a command to span multiple lines.

-thumbnail 250x250^

  • The thumbnail is an ImageMagick specific command similar to the -resize command, but it is optimized for use when explicitly making thumbnails. It will strip out any image profile that it may find in the source file, and you can optionally strip out any color profiles as well (using the -strip option.)
  • The 250x250 is stating the final (in pixels) size that we want our thumbnails to be generated at.
  • The ^ operator at the end of our size lets the convert command know that we want ONE of the dimensions (width or height) to be the size we’ve specified. For example, an image that is 5400px x 3600px will initially be resized down to 375px x 250px, then the 375px width will be cropped in to 250px to get our final 250x250 dimensions. If we don’t do this we end up with a final image that has white empty areas on the sides with a longer dimension:

-gravity center

  • The gravity option tells ImageMagick how to crop into the original image to make our thumbnail. In our case, we’re using center, so the image crop will be from the middle of the original image. There’s lots more info in the gravity documentation if you want to explore other crop options.

For the sake of testing, I’ve grabbed two images – one horizontal and one vertical. I ran through the various options for the -gravity operator and documented the results below. (I used both -thumbnail 250x250^ and -resize 500x500^ to give an exaggerated demo of how resize/thumbnail works with different ratios and image sizes. This also shows why I choose to set both my -thumbnail and -extent to 250x250^ instead of a larger size.)

Click on the images to see them larger.

-extent 250x250

  • The extent option reduces or expands an image to fit in the specified space that we’re setting. In this case 250x250, as this is the final size that we want our image thumbnail to be.

-set filename:fname '%t_thumb'

  • Since we’re going to modify the name of the exported thumbnails, we need to use the ImageMagick set operator. This will assign (or modify) specific settings attached to all the images in the current image sequence. We’re calling our name change value fname, so that we can use it again in the next line.
  • Using %t and adding _thumb gives us our output filename, that will apply to all files. (The %t grabs the filename without directory or extension and since we’re modifying the name, we’re adding the _thumb to it. This could be whatever you want it to be and you could even specify it in a variable at the top of the file.)

    Read more about set here and percent escapes here.


  • And now we’re putting it all together… Using our output_dir variable to specify our output folder, we then include the %[filename:fname] to grab our modified filename from the previous set step. The only new thing we’re adding here is the .jpg extension, as we want all of our exported files to be jpgs. You could change this to any other format and ImageMagick should be smart enough to make the format you specify for your thumbs.


Pretty easy right?

So basically you want to take all of the fun ImageMagick stuff that you learned above and put it together into a file on your computer. So, we’ll need to make the following locally:

  • Your directory full of images that are itching to be resized
  • Your script to do the resizing

I’ll assume that you have neither of these made yet, and are just dumb as a post when it comes to this stuff… That’s fine. Here’s what you do:

Make the directory for your NOT porn

### Changes to your desktop
$ cd $HOME/Desktop

### Makes the directory for your images
$ mkdir Definitely_NOT_Porn

Make the file for your script

### Creates an empty file with your cool name
$ touch

### Opens the file in Atom (You enabled the CLI integration, right?)
### You can use whatever editor here. Substitute with nano
### or Vim if you want to stay on the command line
$ atom

Once you have the file open in your editor, take the code for the script that I have above, copy it and paste it into the file that you just created/opened. Save the script on your Desktop as or whatever.

Put all of your images in the folder

At this point, you’ll want to get together all images that you want to process into thumbnails and drop them into the Definitely_NOT_Porn folder on your Desktop.

Permissions, my dudes

On the command line, navigate to the folder where you saved your script. Since I’m assuming that you followed along and make it on your Desktop, we’ll change to the Desktop (if we’re not already there) with cd $HOME/Desktop and then we want to have at it with the permissions:

### Make the file executable, so we can actually run the damn thing
$ chmod +x

Finally, we’re gonna make those goddamn thumbnails

And since you’re already on the command line and ready to go, let’s run the script and process your files!

$ ./

If you’re stuck or really don’t want to mess with making the script and stuff, you can always grab my version from my utilities repo on Github. The only slight difference in the repo script and the one above is that my repo script is just called You can name it whatever stupid thing you want once you download it.

Did it work?

So, remember in the script when we set our output_dir, right? Well, that’s where your new thumbnails should be living their greatest life now. If you didn’t change anything, they’ll be on your Desktop, in a folder called notporn_thumbnails. Open it up and check out your images.

  • Are they square?
  • Are they 250x250?
  • Are they all named with a _thumb.jpg on the end?
  • Are they all there?

Good. They should be.

Problems? Something all wonky? Did you delete all images on your machine?

Let me know. Seriously. I don’t claim to be the best dude out there at this stuff, but I’ve done it for a bit and I get by. I’m happy to help if you’re having issues or want a pointer on how to setup something a little more complicated based on this script.

I just really wanted to document just how to do this, as it seems like something that I’ve come back to several times over the years. Sure, I could run a batch script in Photoshop, but where’s the fun in that? This way is quicker and once you set it up, you can copy the script and make as many variations as you wanted, expand on it, or even include it in other scripts. Hope it helps in all of your thumbnailing endevors in the future.