0

TIMELAPSE PROJECT

Over a year a new photo has been uploaded every 15 minutes from my webcam (thousands of photos)

I am looking for a simple way to
1. Pick one picture from each day, taken as close as possible to 12:00 midday
2. Then move all selected files to a subfolder

The filename format is YYYYMMDDHHMMSS (ex.20180715035717.jpg)
Date modified is also available in file details.

PS: Date modified/ LastWriteTime is -2 hours from when photo was taken

Any help would be appreciated

Screenshot of folder with files

Example: For each photo taken between 11:50 and 12:10 move to subfolder

LastWriteTime////Length////   Name

15.07.2018     08.37        2655543 20180715103707.jpg


15.07.2018     08.52        3294951 20180715105207.jpg


15.07.2018     09.07        2787347 20180715110707.jpg


15.07.2018     09.27        2632705 20180715112706.jpg


15.07.2018     09.42        2589219 20180715114206.jpg


15.07.2018     10.02        2767032 20180715120208.jpg  - MOVE TO SUBFOLDER


15.07.2018     10.27        2997687 20180715122726.jpg


15.07.2018     10.52        3071746 20180715125224.jpg


15.07.2018     11.13        2981523 20180715131308.jpg


15.07.2018     11.37        3074120 20180715133708.jpg


15.07.2018     11.57        2753426 20180715135708.jpg


15.07.2018     12.17        2575961 20180715141709.jpg


15.07.2018     12.37        2664982 20180715143710.jpg


15.07.2018     12.52        3049712 20180715145210.jpg


15.07.2018     13.16        2637337 20180715151618.jpg


15.07.2018     13.31        2755671 20180715153118.jpg


15.07.2018     13.46        2937633 20180715154618.jpg


15.07.2018     14.07        2591824 20180715160724.jpg


15.07.2018     14.22        2616955 20180715162225.jpg


15.07.2018     14.37        2632948 20180715163725.jpg


15.07.2018     14.52        2760379 20180715165225.jpg


15.07.2018     15.07        3080011 20180715170725.jpg


15.07.2018     15.27        3339818 20180715172706.jpg


15.07.2018     15.42        3136413 20180715174206.jpg


15.07.2018     15.58        3015146 20180715175806.jpg


15.07.2018     16.21        2597969 20180715182111.jpg


15.07.2018     16.41        2627375 20180715184112.jpg


15.07.2018     16.56        2685684 20180715185613.jpg


15.07.2018     17.13        2590604 20180715191313.jpg


15.07.2018     17.37        2621325 20180715193718.jpg


/// REMOVED SOME LINES


16.07.2018     06.08        1956348 20180716080822.jpg


16.07.2018     06.27        2119143 20180716082705.jpg


16.07.2018     06.47        2176428 20180716084706.jpg


16.07.2018     07.02        3243543 20180716090207.jpg


16.07.2018     07.26        2013755 20180716092649.jpg


16.07.2018     07.46        2017713 20180716094649.jpg


16.07.2018     08.01        3565675 20180716100150.jpg


16.07.2018     08.16        3578500 20180716101651.jpg


16.07.2018     08.37        3807611 20180716103705.jpg


16.07.2018     08.57        3728615 20180716105729.jpg


16.07.2018     09.12        3712588 20180716111230.jpg


16.07.2018     09.27        3747855 20180716112730.jpg


16.07.2018     09.42        3744401 20180716114230.jpg


16.07.2018     09.57        3593773 20180716115730.jpg - MOVE TO SUBFOLDER


16.07.2018     10.17        3189216 20180716121732.jpg


16.07.2018     10.33        3400749 20180716123307.jpg


16.07.2018     10.48        3501471 20180716124807.jpg
Jawad
  • 11,028
  • 3
  • 24
  • 37
Eirik
  • 3
  • 4
  • Are you stuck with having to do this on Windows? – Mark Setchell Jan 12 '20 at 20:06
  • 1
    What have you tries so far? Are you looking for the picture taken right before or shortly after 12:00 o'clock noon? _Move the files_ meaning the ones you pick or the all the other pictures? – Theo Jan 12 '20 at 20:12
  • 1
    Also, from the image of the files I can see there is a time difference of 2 hours between the timestamps in the file name and the Date modified (LastWriteTime) of the files. This could be the time diff between UTC and your local time zone. Which "12:00" are you aiming at? – Theo Jan 12 '20 at 20:18
  • please add the TEXT of some of the file names to your Question so that folks will have something to work with. also, as `Theo` mentioned, if you want the LastWriteTime used instead of the file name ... you will need to include that info. last, please show the desired result - which files from the list meet your specification. – Lee_Dailey Jan 12 '20 at 20:23
  • @MarkSetchell Yes stuck on Windows unfortunately – Eirik Jan 12 '20 at 20:29
  • @Theo I have tried Robobasked, but it could only sort on date. Also been looking at PowerShell commands, but my skills here are limited Before or after 12:00 doesnt matter. Since one picture is taken every 15.minute, the scope could for example be between 11:50 and 12:15. The files sorted out should be moved, not the rest since there are so many. I am aware of the 2 hour difference from modified date and filename. Very observant :) Figuring this is just smaller adjustments to the code, I didnt mention it. But the filename time is correct and what I am aming for. Thanks so far! – Eirik Jan 12 '20 at 20:44
  • @Lee_Dailey Thanks for your comments. I have added a list with filenames and info, including two occurences of files I want to sort into subfolder – Eirik Jan 12 '20 at 21:09
  • @Eirik - you are welcome! it looks like `TessellatingHeckler` has provided you with an answer. if you don't want to use the file date, then you can either add the offset to the file date OR parse the file name with `[datetime]::ParseExact()` – Lee_Dailey Jan 12 '20 at 21:14

3 Answers3

1

Assuming the "Date Modified" column is valid, so you can use that and don't have to extract the date from the filename, PowerShell handles System.DateTime objects which let you get the .Date out - i.e. the day without the time.

The steps could be:

  • Group the pictures by date, so there's a group for each day
  • Use this date +12 hours for the midday time for each group
  • Subtract the file date from the midday date, and take the absolute value to remove +/- sign
  • sort to get the smallest distance-from-midday

Untested, but I think roughly right, PowerShell example:


    Get-ChildItem -Path 'c:\pictures' | 

        # group the pictures by day
        Group-Object -Property {$_.LastWriteTime.Date} |

        # loop over each day-group
        ForEach-Object {    

            # get the day back from the group name, make it midday
            $midday = (Get-Date $_.Name).AddHours(12)

            # sort the files for that day,
            # by closeness to midday,
            # pick the nearest 1
            # Copy it to ... ? you didn't say where. Some subfolder, I guess

            $_.Group | Sort-Object {
                    [math]::abs(($_.LastWriteTime - $midday).TotalSeconds)} | 
                    Select-Object -First 1
                } |
                Copy-Item -Destination 'c:\pictures\subfolder' -WhatIf
        }

You'll have to remove the -WhatIf to get it to actually do stuff, and change copy-item to move-item to get it to scramble your data.

TessellatingHeckler
  • 27,511
  • 4
  • 48
  • 87
1

I suspect something similar to this should do the trick:

Get-ChildItem -Path C:\SomePath\ToPictures\ -Filter *.jpg -Recurse | 
    Where-Object -FilterScript {!$_.PSIsContainer -and $_.LastWriteTime.TimeOfDay.TotalHours -gt 11.875 -and $_.LastWriteTime.TimeOfDay.TotalHours -lt 12.125} | 
    Move-Item -Destination C:\TargetPath\

Get all the *.jpg files in C:\SomePath\ToPictures. Ensure they are not folders, and were written after 11:52:30 AM but before 12:07:30 PM (15 minute interval). Then, move them to C:\TargetPath.

Note: You may wish to test with Copy-Item first, before using Move-Item.

Hope this helps.

leeharvey1
  • 1,316
  • 9
  • 14
  • Thank you! Very simple. This is what I was looking for. But the script seems to run copy/move twice. Can you see why from the error? Copy-Item : Cannot overwrite the item C:\test\Pickouts\20180720120416.jpg with itself. At line:3 char:5 + Copy-Item -Destination C:\test\Pickouts\ + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + CategoryInfo : WriteError: (C:\test\Pickouts\20180720120416.jpg:String) [Copy-Item], IOException + FullyQualifiedErrorId : CopyError,Microsoft.PowerShell.Commands.CopyItemCommand – Eirik Jan 12 '20 at 21:28
  • Is it possible that you may already have some subfolders with indented target files created under the source path that might contain duplicate copies of target files (being picked-up by `-Recurse`)? If so, try adding `-Force -ErrorAction SilentlyContinue` to the last `Copy-Item` cmdlet, if you simply want to overwrite them when encountered. – leeharvey1 Jan 13 '20 at 12:17
  • Otherwise, if your *.jpg images are in a single folder, simply remove `-Recurse` from the first `Get-ChildItem` cmdlet. – leeharvey1 Jan 13 '20 at 12:28
0

If you want to use the timestamps in the file names, the below code should do what you want:

$sourceFolder = 'D:\test'
$destination  = 'D:\PicturesAroundNoon'

# if the destination path does not exist, ceate it
if (!(Test-Path -Path $destination -PathType Container)) {
    $null = New-Item -Path $destination -ItemType Directory
}
# get a list of FileInfo objects for the files to move
Get-ChildItem -Path $sourceFolder -Filter '*.jpg' -File | 
    Where-Object { $_.BaseName -match '^\d{14}$' -and $_.Name.Substring(8,2) -match '11|12' } | 
    Group-Object @{Expression = {$_.BaseName.Substring(0,8)}} | 
    ForEach-Object {
        if ($_.Group.Count -eq 1) { $fileToMove = $_.Group[0] }  # return the only file for thatdate
        else {
            if ($_.Group.Count -eq 2) {
                $index = 0
            }
            else {
                $index = [math]::Floor($_.Group.Count / 2)
            }
            # get the middle two files from the collection and test which is closest to 12:00
            $file1, $file2 = ($_.Group | Sort-Object)[$index..($index + 1)]
            # get the dates from the file BaseName property
            $date1 = [datetime]::ParseExact($file1.BaseName, 'yyyyMMddHHmmss', $null)
            $date2 = [datetime]::ParseExact($file2.BaseName, 'yyyyMMddHHmmss', $null)
            $noon  = Get-Date -Year $date1.Year -Month $date1.Month -Day $date1.Day -Hour 12 -Minute 0 -Second 0
            # get the time distance to 12:00 in seconds
            $dif1 = [math]::Abs(($date1 - $noon).TotalSeconds)
            $dif2 = [math]::Abs(($date2 - $noon).TotalSeconds)
            $fileToMove = if ($dif1 -lt $dif2) { $file1 } else { $file2 }
        }
        # now move the file to its destination
        $fileToMove | Move-Item -Destination $destination -WhatIf
    }

Remove the -WhatIf if you are satisfied with the results shown in the console

Theo
  • 57,719
  • 8
  • 24
  • 41