Solved

Move files based on their timestamp

Posted on 2015-02-20
15
143 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
3 Use Cases for Connected Systems

Our Dev teams are like yours. They’re continually cranking out code for new features/bugs fixes, testing, deploying, testing some more, responding to production monitoring events and more. It’s complex. So, we thought you’d like to see what’s working for us.

 
LVL 24

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 24

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
 
LVL 24

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 53

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 24

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 53

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 53

Expert Comment

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

~bp
0

Featured Post

DevOps Toolchain Recommendations

Read this Gartner Research Note and discover how your IT organization can automate and optimize DevOps processes using a toolchain architecture.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

A short article about a problem I had getting the GPS LocationListener working.
Since upgrading to Office 2013 or higher installing the Smart Indenter addin will fail. This article will explain how to install it so it will work regardless of the Office version installed.
In this fourth video of the Xpdf series, we discuss and demonstrate the PDFinfo utility, which retrieves the contents of a PDF's Info Dictionary, as well as some other information, including the page count. We show how to isolate the page count in a…
With the power of JIRA, there's an unlimited number of ways you can customize it, use it and benefit from it. With that in mind, there's bound to be things that I wasn't able to cover in this course. With this summary we'll look at some places to go…

770 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