Organize Photos with Powershell

Posted On 2016-05-09 by dwirch
Tags: Powershell Scripting Tip Windows
Views: 1665

Like a lot of smartphone users, I like to take pictures. These pictures get automatically synced to my cloud storage, dumping them in a single folder called "Camera Roll". I came up with a quick Powershell script to organize these photos by year and month.

I use a Windows phone, which automatically syncs up with my OneDrive, and thus gets all my devices up to date with pictures that I take with the phone. Users of other devices and services might run into this same problem: All your photos get dumped in the same folder. After awhile, simply viewing the directory listing takes a good amount of time, especially in the web interface.

I needed a quick, automated way to organize the thousands of pictures into subdirectories. The system I came up with was first by year, then by month, with "raw" or "fresh" photos in the "root" directory. So for example, the directory structure including the root directory and the year 2016, with the months January through April, each with 3 pictures would kind of look like this indented list:

  • Camera Roll
    • 2016
      • 01
        • picture2357.jpg
        • picture2358.jpg
        • picture2359.jpg
      • 02
        • picture2360.jpg
        • picture2361.jpg
        • picture2362.jpg
      • 03
        • picture2363.jpg
        • picture2364.jpg
        • picture2365.jpg
      • 04
        • picture2366.jpg
        • picture2367.jpg
        • picture2368.jpg

The problem was that over the years, I haved owned a variety of phones and cameras, all which have dropped picture files into the Camera Roll folder. Not all of the device date-encode their filenames, and instead utilize a simple counter for naming the picture files. Another problem was that each device seemed to use a different format (JPG, GIF, BMP, PNG, etc).

PowerShell can grab all this and process the files with no problem. Here is the script that I came up with in about 10 minutes:

$MyFiles=get-childitem -path c:\OneDrive\MyPictures\* -include *.png,*.jpeg,*.gif,*.jpg,*.psd,*.bmp

ForEach($File in $MyFiles)
$fMonth="{0:00}" -f $file.LastWriteTime.Month

$PathExists=Test-Path $fYear
if($PathExists -eq $false) { mkdir $fYear | out-null }

$PathExists=Test-path $fYear\$fMonth
if($PathExists -eq $false) { mkdir $fYear\$fMonth | out-null }

write-host "Moving $File to $fYear\$fMonth" -ForegroundColor Green
move-item $file $fYear\$fMonth

For those of you who may not be conversant in PowerShell, I'll explain what is going on here.

First, a list of picture files from the "root" directory is stored in $MyFiles. The -include switch is used here because it can reference several different values, whereas -filter can only reference one value. This way, we can get a list of all the picture files into an array in one shot.

Next a loop is started, which steps through all the files in $MyFiles.

The next two lines simply grab the year and month from the file, using the LastWriteTime attribute, storing each value in the appropriate variables (fYear and fMonth).

Now we need to see if the target path actually exists. These four lines can be cleaned up a bit, but this works, and is ok for a quick and dirty script. In these four lines, the path for the year and momth is checked for existence, and if it does not exist, they are created.

Finally, the file is moved to the target path. And since I like to see what is going with my scripts, a notification is written to screen prior to the move.

Like I said, not too complicated, and it helps me to keep my pictures organized. This could also be modified to work with other file types, simply by changing the parameters on the -include switch on the first line. It could used for, say, archiving log files to an alternate location.

I hope you have found this useful!

Improvements? Ideas?

About the Author

dwirch has posted a total of 174 articles.

You can find more information from dwirch by visiting

Comments On This Post

No comments on this post yet!

Do you have a thought relating to this post? You can post your comment here. If you have an unrelated question, you can use the Q&A section to ask it.

Or you can drop a note to the administrators if you're not sure where you should post.

Your IP address is:

Before you can post, you need to prove you are human. If you log in, this test goes away.

Recent Forum Posts

New security implemented
dwirch posted on July 23, 2017 at about 6:58 in Site News

Fold Code Manager into main KB?
VB6Boy posted on July 22, 2017 at about 14:42 in Site News

Fold Code Manager into main KB?
dwirch posted on July 22, 2017 at about 14:41 in Site News

Fold Code Manager into main KB?
dwirch posted on July 21, 2017 at about 22:46 in Site News

Fold Code Manager into main KB?
dwirch posted on July 20, 2017 at about 7:55 in Site News

Job Spammer: Sam Mallon
dwirch posted on July 18, 2017 at about 18:36 in Spammers