I want semi-automate copying and categorizing DCIM files from my iPhone to my computer, keeping "related" camera images together and separate from screenshots, downloaded jpeg's, gifs, mpeg's, png's, etc.

On my iPhone I have a bunch of downloaded images (from Pinterest, Tumblr, etc). I also have bunch of related jpg/mp4 pictures taken with the iPhone camera that are in related pairs, one following the other in filename order. Apparently the iPhone camera records both a jpeg image and a multi-frame mp4 movie for each picture taken. Downloaded images are just single jpegs, gifs, mp4's etc.

I would like the script to reside on the local computer and run manually after the iPhone is mounted.

The iPhone image paths are:'mtp://Scottc's iPhone/Internal Storage/DCIM/291APPLE', 'mtp://Scottc's iPhone/Internal Storage/DCIM/292APPLE', 'mtp://Scottc's iPhone/Internal Storage/DCIM/293APPLE', etc.

I don't have control over the subdirectory names (such as 291APPLE, 292APPLE, 293APPLE, etc. but they always start with a (seemingly random) 3-digit number and always end in "APPLE". There can be one or ten. It just depends on iOS and the number of files. The subdirectories are read-only but the files themselves are read-write so can be deleted later.

So, I need to work with all the files recursively up to 'mtp://Scottc's iPhone/Internal Storage/DCIM/'.

The directory listing in each subfolder on the iPhone looks something like this:

*image001.jpg* <-- downloaded *image002.jpg* <-- downloaded *image003.jpg* <-- camera image a *image004.mp4* <-- camera image b *image005.jpg* <-- downloaded *image006.jpg* <-- downloaded *image007.jpg* <-- downloaded *image008.jpg* <-- downloaded *image009.jpg* <-- camera image a *image010.mp4* <-- camera image b *image011.jpg* <-- downloaded

So files 003 and 004 are related, and files 009 and 010 are related. All the files in Scottc's iPhone/DCIM/* have unique names.

I would like to copy only the related images to directory A and the remaining images (downloads, which can be of any type jpg, gif, mp4, etc.) to Directory B.

Can anyone help with the Powershell logic and code that would make this possible? I really have no idea how to accomplish this. Maybe there is a better way or a utility someone already wrote? If so, I have been unable to find it and dealing with hundreds of images at a time is really tedious. This seems like the perfect application for Powershell.

I think I need to loop through the files, identify the first *.mp4 file, put the filename in to a variable, copy the *.mp4 file to Directory A, then subtract the value 1 from the variable to match the preceding related *.jpg filename in alphabetical order and copy that to Directory A.

Rinse and Repeat.

Then copy the remaining unrelated files (of any type) to Directory B.

So, in the end I have the following directory structure:

On the iPhone:  

(leave the original files as is)  

Directory A  

image003.jpg    <-- camera image a  
image004.mp4    <-- camera image b  
image009.jpg    <-- camera image a  
image010.mp4    <-- camera image b  

Directory B  

image001.jpg    <-- downloaded  
image002.jpg    <-- downloaded  
image005.jpg    <-- downloaded  
image006.jpg    <-- downloaded  
image007.jpg    <-- downloaded  
image008.jpg    <-- downloaded  
image011.jpg    <-- downloaded 

Finally, ask the user if they want to delete the iPhone originals (I can handle that part, I think) but not the iPhone directories (the permissions issue mentioned above...iOS takes care of the directory structure).

One gotcha I think is that a downloaded movie ending in *.mp4 will be matched with an unrelated *.jpg file which was downloaded just previously. Unless someone has an elegant way to handle that. I can live with that minor limitation. I've noticed that the related jpg/mp4 files have the same hh:ss timestamp if that helps. Downloaded images/movies/gifs never match time-wise. Maybe matching the timestamps is easier? No idea how to accomplish that either.

Where I am really confused is the handling of the filename variable(s), the mathematical -1 logic when working with filenames and how to handle the remaining filenames (in an array, or through iteration?). The copy, move, name match, etc. I think I can work out through trial and error--but feel free to elaborate. What some can do on the fly takes me hours, often ending in failure and frustration :-(

Can anyone help? My Powershell skills are up to about Chapter 3-ish so I'm really struggling.

  • Ooh this is a toughie – var firstName Jun 30 '17 at 16:18
  • I'll have you a script in a jiffy one sec – var firstName Jun 30 '17 at 17:06
  • Are the filenames of downloaded videos still IMAGE###.mp4? – var firstName Jun 30 '17 at 17:33

This is a little late, but I tweaked this script a little for iPhone's specific subfolders: https://blog.daiyanyingyu.uk/2018/03/20/powershell-mtp/

What is changed from the original script is the last part which now loops through the subfolders in the DCIM folder. This script then moves all the files to the destination. It doesn't answer your question directly, but this solves the MTP o drive part at least. Change:

$items = @( $folder.GetFolder.items() | where { $_.Name -match $filter } )


$subfolders = $folder.GetFolder.items()
foreach ($subfolder in $subfolders) {
    $items = @( $subfolder.GetFolder.items() | where { $_.Name -match $filter } )

and then an extra } at the end of course.

Example usage after change:

./mptcopy.ps1 -phoneName 'Apple iPhone' -sourceFolder '\Internal Storage\DCIM' -targetFolder 'C:\pics' -filter '(.jpg)|(.jpeg)|(.png)|(.gif)|(.bmp)'

Try this and keep us up to date on if it works or not:

Edit: I forgot to search each directory. Should be fixed now.

$directoryA = "%userprofile%\Pictures\Directory A"
$directoryB = "%userprofile%\Pictures\Directory B"
$items = Get-ChildItem ".\\image*"  -Recurse | ForEach-Object { if (!($_.PSIsContainer)) { $_}}
$i = 0
$mp4s = @()
$associatedImgs = @()
 ForEach($item in $items) {
    If(($items[$items.IndexOf($item)].Extension).Equals(".mp4")) {
        $mp4s += $i
        $associatedImgs += $i - 1
    $i += 1

ForEach($mp4 in $mp4s) {
    Copy-Item -Path $items[$mp4].FullName -Destination $directoryA -Force -PassThru -Verbose
    Copy-Item -Path $items[$mp4 - 1].FullName -Destination $directoryA -Force -PassThru -Verbose

ForEach($item in $items) {

    } ElseIf($associatedImgs.Contains($items.IndexOf($item))) {

    } Else {
        Copy-Item -Path $items[$item].FullName -Destination $directoryB -Force -PassThru -Verbose

  • This script does a great job of processing a directory for file types and then doing something specific with those files types. However, this is only part of the answer. We also need a way of accessing the files on the iPhone, which isn't exposed to the filesystem in a straightforward way, such as an external drive... I'm cross-referencing several articles right now to see if I can piece this all together, because I'm after the same thing as @Scott – JustaDaKaje Apr 16 '19 at 2:59

If the creationtime of the .mp4 / .jpg pairs is reliable,
you could try grouping the files by this property:

Get-ChildItem -Recurse -include '*.htm','*.ps1'|
  Group-Object Creationtime|
    ForEach-Object {If($_.Group.Count -eq 2){$_.Group.Fullname;"---"}}

This will only output pairs of two matching times for a check.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.