'Batch file to move files by date modified

I have written a batch file, which creates empty folders for each date. My next task is to create another batch file, which moves each file in a directory, into the relevant date folder, based on their date modified. I have read numerous forums and articles on how I can achieve this, but with my limited batch file knowledge, I just cannot seem to get it to work. The code I currently have is shown below, though this does not seem to pull in the date modified. Any help is much appreciated!

SET directory="\directory\path\archive"

FOR /f %%a in ('dir /b "%directory%"') do (

SET fdate=%%~Ta

MOVE "%directory%\%%a" "%directory%\%fdate%"


Solution 1:[1]

Until you provide more info as to format of dates, I can't give a definitive answer. But I can show you how I would do it on my machine.

I use yyyy-mm-dd format within file and folder names, so December 13, 2011 would be 2011-12-13. My machine uses mm/dd/yyyy format for dates (12/13/2011). So I would need to translate the %%~tF output from 12/13/2011 into 2011-12-13. Note - / cannot be used used in file or folder names.

So this code would do what you want on my machine:

set "source=\directory\path\archive"
set "targetRoot=\directory\path\archive"
for %%F in ("%source%\*") do (
  for /f "tokens=1,2,3 delims=/ " %%A in ("%%~tF") do (
    move "%%~fF" "%targetRoot%\%%C-%%A-%%B"
  )
)

Addendum - Question in comment asks for method to left pad a number with zeros for dir creation. I see two easy choices. (This really should be a different question)

This first method is simple but tedious and not practical as a general solution

for %%A in (01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31) do ...

The second method is a general solution. Since your assignment is within parentheses, you need to use delayed expansion.

setlocal enableDelayedExpansion
for /l %%A in (1 1 31) do (
  set "day=0%%A"
  set "day=!day:~-2!
  ...
)

You increase the number of leading zeros by adding more 0 to the front and then increasing the number of characters you preserve in the substring operation.

BUT - why prepopulate the directories? Your strategy will add directory days that don't exist in the calendar, plus you are likely to have many unused folders for which no files were modified on that day. Better to create the folders only as needed. Then the 0 padding is already done for you, and no unneeded folders are created.

set "source=\directory\path\archive"
set "targetRoot=\directory\path\archive"
for %%F in ("%source%\*") do (
  for /f "tokens=1,2,3 delims=/ " %%A in ("%%~tF") do (
    if not exist "%targetRoot%\%%C\%%A\%%B" mkdir "%targetRoot%\%%C\%%A\%%B"
    move "%%~fF" "%targetRoot%\%%C\%%A\%%B"
  )
)

Solution 2:[2]

My answer is a simple FOR loop who check all files in current directory and take date from eachone file. Create a folder in format yyyy\yyyy-mm and move file into it.

@echo off
rem not %var% but !var! give us access to internal loop variable value with enabledelayedexpansion.
setlocal enabledelayedexpansion
FOR %%V IN (*.*) DO (
SET filedate=%%~tV
rem echo !filedate!
SET fileyear=!filedate:~6,4!
rem echo !fileyear!
SET filemonth=!filedate:~3,2!
rem echo !filemonth!
rem create directory as yyyy\yyyy-MM
mkdir !fileyear!\!fileyear!-!filemonth! 2>nul
echo move %%V !fileyear!\!fileyear!-!filemonth!\
move %%V !fileyear!\!fileyear!-!filemonth!\ >nul
)

TIP: The filemonth and fileyear variable probably should have other numbers to cut proper yyyy/mm for your country/region timestamp. TIP: This FOR move the script itself to into one of subdirectory, I run it as Windows Shortcut with enter a Location Path - then this script run in proper place.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1
Solution 2 SiB