Solved

Move files based on their timestamp

Posted on 2015-02-20
15
136 Views
Last Modified: 2015-02-21
Hi Experts, I'm trying to write a batch file or a VBA script that will help me sort my photos based on month/year (I have thousands of them across multiple folders).  I'd like the script to point to a parent directory and scan through all sub directories moving all files to a destination folder based on the time stamp as follows:

2013 Photos
   01 Jan 2013
   02 Feb 2013
   03 Mar 2013
   ....
2014 Photos
   01 Jan 2014
   02 Feb 2014

I will pre-populate the destination folders under C:/Sorted Photos.  I'll also include an "Unsorted" folder to catch anything that can't be mapped.  I think this should be pretty straight forward, but I can't figure out where to start.

thanks in advance
0
Comment
Question by:JamesCbury
  • 6
  • 4
  • 3
  • +1
15 Comments
 
LVL 4

Expert Comment

by:Harper McDonald
ID: 40622111
Try using the Sort-Object Cmdlet and pipe that into a .CSV file, e.g.   xxxxx  | Export-Csv c:\test.csv

https://technet.microsoft.com/en-us/library/ee176968.aspx

-Harp
0
 

Author Comment

by:JamesCbury
ID: 40622152
Thanks, that's helpful, but I still don't understand how to use that to actually move the files.
0
 
LVL 4

Expert Comment

by:Harper McDonald
ID: 40622164
0
 
LVL 23

Expert Comment

by:NVIT
ID: 40622183
Here's a .bat version.
Revised...
...to make folder names like '01 Jan 2015'.
...to make top level folders like '2015 Photos'.

Notes:
- Adjust SrcDir and TgtTop variables to match your actual folder names.
- Try it on a small, isolated sample of files first.
@echo off
REM Move files to date-named folders, i.e. MM DD YYYY
setlocal ENABLEDELAYEDEXPANSION

set SrcDir=C:\All Photos
set TgtTop=C:\Sorted Photos
if not exist "%TgtTop%" md "%TgtTop%"

set TmpFile="%temp%.\tmp.vbs"
if exist "%TmpFile%" del /q "%TmpFile%"

:DoIt
pushd %SrcDir%
for %%A in (*.*) do (
  set FNDate=%%~tA
  set FNYYYY=!FNDate:~6,4!
  set FNMM=!FNDate:~0,2!
  set FNDD=!FNDate:~3,2!
  echo>%TmpFile% wsh.Echo monthname^(month^("!FNMM!-!FNDD!-!FNYYYY!"^), true^)
  for /f %%a in ('cscript //nologo "%TmpFile%"') do set FNMMM=%%a
  set TgtDirRoot=%TgtTop%\!FNYYYY! Photos
  set TgtDir=!FNMM! !FNMMM! !FNYYYY!
  if not exist "!TgtDirRoot!" md "!TgtDirRoot!"
  if not exist "!TgtDirRoot!\!TgtDir!" (echo Processing "!TgtDirRoot!\!TgtDir!"& md "!TgtDirRoot!\!TgtDir!")
  move "%%A" "!TgtDirRoot!\!TgtDir!"
)
popd
goto :eof

Open in new window

0
 

Author Comment

by:JamesCbury
ID: 40622546
That is awesome - better then I could have expected - THANK YOU.  Quick question though - is it possible to have it scan all sub directories within C:\All Photos and move those photos too?
0
 
LVL 23

Expert Comment

by:NVIT
ID: 40622643
You're welcome, James.

Did my solution work for you? I.e. did it move all the files in "C:\All Photos" into the correct folders?

Now, you'd like to extend it to process subdirectories of "C:\All Photos", also? So that, basically all the files will be moved from their current subfolder to, for example, a folder like "01 Jan 2015"?
0
 

Author Comment

by:JamesCbury
ID: 40622704
yes, the script worked great for moving the files from "C:\All Photos" into the correct folders (I was impressed how you were able automatically create the folder if it did not exist).

The extension is just as you stated. "C:\All Photos" has several sub directories in it (and some of those have further sub directories). I'd like the script to loop through them all. I can repost that as a separate question if you like.
0
What Security Threats Are You Missing?

Enhance your security with threat intelligence from the web. Get trending threat insights on hackers, exploits, and suspicious IP addresses delivered to your inbox with our free Cyber Daily.

 
LVL 23

Assisted Solution

by:NVIT
NVIT earned 250 total points
ID: 40623439
Here you go, James.

Moves files in source and sub-folders into folders like '2015 Photos\01 Jan 2015', according to the file's date.

Revised...
...to process sub-folders.
...other minor revisions.

Notes:
- Adjust SrcDir and TgtTop variables to match your actual folder names.
- Try it on a small, isolated sample of files first.

@echo off
setlocal ENABLEDELAYEDEXPANSION

REM Move files to date-named folders, i.e. "YYYY Photos\MM DD YYYY",
REM according to the file's date.
REM Duplicates are not moved.
REM General results are logged to %temp% folder

set SrcDir=C:\All Photos
set TgtTop=C:\Sorted Photos

set ThisBAT=%0
set ThisBATFN=%~n0
set ThisBATLog=%temp%\%~n0_log.txt

echo %date% %time% BEGIN %ThisBATFN%%~x0 "%SrcDir%">>"%ThisBATLog%"
if not exist "%SrcDir%" (echo %date% %time% Missing source folder: "%SrcDir%">>"%ThisBATLog%"& goto :Done)
if not exist "%TgtTop%" md "%TgtTop%" 2>>"%ThisBATLog%"

set TmpFile="%temp%.\tmp.vbs"
if exist "%TmpFile%" del /q "%TmpFile%" 2>>"%ThisBATLog%"

:DoIt
echo Processing...
for /r "%SrcDir%" %%A in (*.*) do (
  set FNDate=%%~tA
  set FNYYYY=!FNDate:~6,4!
  set FNMM=!FNDate:~0,2!
  set FNDD=!FNDate:~3,2!
  echo>%TmpFile% wsh.Echo monthname^(month^("!FNMM!-!FNDD!-!FNYYYY!"^), true^)
  for /f %%a in ('cscript //nologo "%TmpFile%"') do set FNMMM=%%a
  set TgtDirRoot=%TgtTop%\!FNYYYY! Photos
  set TgtDir=!FNMM! !FNMMM! !FNYYYY!
  if not exist "!TgtDirRoot!" md "!TgtDirRoot!" 2>>"%ThisBATLog%"
  if not exist "!TgtDirRoot!\!TgtDir!" (echo Processing "!TgtDirRoot!\!TgtDir!"& md "!TgtDirRoot!\!TgtDir!" 2>>"%ThisBATLog%")
  if not exist "!TgtDirRoot!\!TgtDir!\%%~nxA" (
    REM The MOVE command overwrites existing files by default
    move "%%A" "!TgtDirRoot!\!TgtDir!">nul 2>>"%ThisBATLog%"
	) else (
    echo %date% %time% "%%A" not moved>>"%ThisBATLog%"
  )
)
goto :Done

:Done
echo %date% %time% END %ThisBATFN%%~x0 "%SrcDir%">>"%ThisBATLog%"

Open in new window

0
 
LVL 51

Expert Comment

by:Bill Prew
ID: 40623526
Based on your original requirements I think we can simplify a bit, and increase speed too.  I am sharing this as much for NewVillageIT to ponder, as well as to solve the problem.  Adjust paths to your needs and give it a test. A few notes on this approach:

It gathers all file names at once first via DIR /S command.
Rather than build and call a VBS script for every file found to get the month abbreviation, use a BAT subroutine for that.
Removes leading 0 from month and day as requested.
No need to create dest folders one level at a tie, MD will create all parent folders as needed.

Wasn't sure if you wanted to move the duplicates to the Unsorted folder, so didn't add that in until you shared more info on that detail.  Hope this is useful.

@echo off
setlocal EnableDelayedExpansion

REM Define from and to folders
set FromDir=B:\EE\EE28621415\From
set DestDir=B:\EE\EE28621415\To

REM Make sure from folder exists, exit if not
if not exist "%FromDir%" (
  echo From folder not found [%FromDir%]
  exit /b
)

REM Process all files in all folders of from folder
for /f "tokens=*" %%A in ('dir /a-d /b /s "%FromDir%\*.*"') do (

  REM Extract last update date components for this file
  set FileDate=%%~tA
  set /a MM=1!FileDate:~0,2! - 100
  set /a DD=1!FileDate:~3,2! - 100
  set YYYY=!FileDate:~6,4!

  REM Translate month number into 3 character abbreviation
  call :GetMonth !MM!

  REM Build folder name to move file to as [dest folder]\DD Mmm YYYY
  set DestPath=%DestDir%\!DD! !MMM! !YYYY!\

  REM Create dest folder if it doesn't exist (creates any missing parents as well)
  if not exist "!DestPath!" md "!DestPath!"

  REM If file doesn't exist in dest folder, move it, else skip it
  if not exist "!DestPath!%%~nxA" (
    move "%%~A" "!DestPath!" > NUL
  ) else (
    echo Duplicate error copying [%%~A] to [!DestPath!], file skipped.
  )
)

exit /b

REM Small subroutine to map a month number to it's 3 character abbreviation
:GetMonth [month-number]
  for /f "tokens=%1 delims=," %%a IN ("Jan,Feb,Mar,Apr,May,Jun,Jul,Aug,Sep,Oct,Nov,Dec") do set MMM=%%a
  exit /b

Open in new window

~bp
0
 

Author Comment

by:JamesCbury
ID: 40623684
Thanks NewVillageIT - the updated scripts works perfectly - all my sub folders are taken into account.

Bill I like your solution as well - it does run quite a bit quicker (though efficiency is not a driving factor for me).  the only thing it missed was the creation of parent folders in the destination directory (i.e., 2013 Photos, 2014 Photos, 2015 Photos, etc).  his is important for me as it helps me to sort my files.

thanks for all the help!
0
 
LVL 23

Expert Comment

by:NVIT
ID: 40623711
@Bill... I appreciate your solution. I've hawked your methods into my toolbox, if you don't mind... hehe.

@James... Glad it worked for you. I forgot to mention that any skipped files are logged in the *_log.txt for you to examine.
0
 
LVL 51

Accepted Solution

by:
Bill Prew earned 250 total points
ID: 40623715
Ah yes, sorry I forgot the collector folders, try this.

@echo off
setlocal EnableDelayedExpansion

REM Define from and to folders
set FromDir=B:\EE\EE28621415\From
set DestDir=B:\EE\EE28621415\To

REM Make sure from folder exists, exit if not
if not exist "%FromDir%" (
  echo From folder not found [%FromDir%]
  exit /b
)

REM Process all files in all folders of from folder
for /f "tokens=*" %%A in ('dir /a-d /b /s "%FromDir%\*.*"') do (

  REM Extract last update date components for this file
  set FileDate=%%~tA
  set /a MM=1!FileDate:~0,2! - 100
  set /a DD=1!FileDate:~3,2! - 100
  set YYYY=!FileDate:~6,4!

  REM Translate minth number into 3 character abbreviation
  call :GetMonth !MM!

  REM Build folder name to move file to as [dest folder]\DD Mmm YYYY
  set DestPath=%DestDir%\!YYYY! Photos\!DD! !MMM! !YYYY!\

  REM Create dest folder if it doesn't exist (creates any missing parents as well)
  if not exist "!DestPath!" md "!DestPath!"

  REM If file doesn't exist in dest folder, move it, else skip it
  if not exist "!DestPath!%%~nxA" (
    move "%%~A" "!DestPath!" > NUL
  ) else (
    echo Duplicate error copying [%%~A] to [!DestPath!], file skipped.
  )
)

exit /b

REM Small subroutine to map a month number to it's 3 character abbreviation
:GetMonth [month-number]
  for /f "tokens=%1 delims=," %%a IN ("Jan,Feb,Mar,Apr,May,Jun,Jul,Aug,Sep,Oct,Nov,Dec") do set MMM=%%a
  exit /b

Open in new window

0
 

Author Comment

by:JamesCbury
ID: 40623741
Thanks that did the trick!  The only thing I updated was to use the MM instead of the DD when naming the folders (this lets me sort them in descending order)  showing the last updated date within that month didn't really do much for me. I reposted below with the updates.

Thanks again.
@echo off
setlocal EnableDelayedExpansion

REM Define from and to folders
set FromDir=B:\EE\EE28621415\From
set DestDir=B:\EE\EE28621415\To

REM Make sure from folder exists, exit if not
if not exist "%FromDir%" (
  echo From folder not found [%FromDir%]
  exit /b
)

REM Process all files in all folders of from folder
for /f "tokens=*" %%A in ('dir /a-d /b /s "%FromDir%\*.*"') do (

  REM Extract last update date components for this file
  set FileDate=%%~tA
  set /a MM=1!FileDate:~0,2! - 100
  set /a DD=1!FileDate:~3,2! - 100
  set YYYY=!FileDate:~6,4!

  REM Translate month number into 3 character abbreviation
  call :GetMonth !MM!

  REM Build folder name to move file to as [dest folder]\MM Mmm YYYY
  set DestPath=%DestDir%\!YYYY! Photos\!MM! !MMM! !YYYY!\

  REM Create dest folder if it doesn't exist (creates any missing parents as well)
  if not exist "!DestPath!" md "!DestPath!"

  REM If file doesn't exist in dest folder, move it, else skip it
  if not exist "!DestPath!%%~nxA" (
    move "%%~A" "!DestPath!" > NUL
  ) else (
    echo Duplicate error copying [%%~A] to [!DestPath!], file skipped.
  )
)

exit /b

REM Small subroutine to map a month number to it's 3 character abbreviation
:GetMonth [month-number]
  for /f "tokens=%1 delims=," %%a IN ("Jan,Feb,Mar,Apr,May,Jun,Jul,Aug,Sep,Oct,Nov,Dec") do set MMM=%%a
  exit /b

Open in new window

0
 

Author Closing Comment

by:JamesCbury
ID: 40623744
This is why I love Experts Exchange - there is always a better way to do something!
0
 
LVL 51

Expert Comment

by:Bill Prew
ID: 40623761
Great, glad that was helpful.

~bp
0

Featured Post

How to improve team productivity

Quip adds documents, spreadsheets, and tasklists to your Slack experience
- Elevate ideas to Quip docs
- Share Quip docs in Slack
- Get notified of changes to your docs
- Available on iOS/Android/Desktop/Web
- Online/Offline

Join & Write a Comment

Does the idea of dealing with bits scare or confuse you? Does it seem like a waste of time in an age where we all have terabytes of storage? If so, you're missing out on one of the core tools in every professional programmer's toolbox. Learn how to …
Deploying a Microsoft Access application in a Citrix environment is not difficult but takes a few steps. However, Citrix system people are often of little help, as they typically know next to nothing about Access. The script provided here will take …
In this fifth video of the Xpdf series, we discuss and demonstrate the PDFdetach utility, which is able to list and, more importantly, extract attachments that are embedded in PDF files. It does this via a command line interface, making it suitable …
In this seventh video of the Xpdf series, we discuss and demonstrate the PDFfonts utility, which lists all the fonts used in a PDF file. It does this via a command line interface, making it suitable for use in programs, scripts, batch files — any pl…

747 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

13 Experts available now in Live!

Get 1:1 Help Now