Link to home
Start Free TrialLog in
Avatar of Luis Diaz
Luis DiazFlag for Colombia

asked on

Windows batch: archive files based on monthly folder v2

Hello experts,

The following procedure allows me to archive files based on a variable on a monthly folder.
It comes from the following question: https://www.experts-exchange.com/questions/29154852/Windows-batch-move-files-based-on-modified-date-in-monthly-folders.html
@echo off
setlocal EnableDelayedExpansion
set CurrentDir=%~dp0
REM Define base for folders, files, and days to keep files before moving
set InputFolder="%CurrentDir%\Files1","%CurrentDir%\Files2","%CurrentDir%\Files3"
set ArchiveFolder=%CurrentDir%Archive
set LogFile="%CurrentDir%\log.txt"
set KeepDays=2

REM Delete any old log file
if exist "%LogFile%" del "%LogFile%"

rem Calculate date to keep files older than
call :CalcKeepDate

REM Loop over each input folder to work
for %%F in (%InputFolder%) do (
    if exist "%%~F\" (
        call :ProcessFolder "%%~F\"
    ) else (
        echo *WARNING* Input folder "%%~F" does not exist.
    )
)

REM Done
exit /b


:CalcKeepDate
    rem Build vbscript helper to calculate file date minus keep days
    set TempVbs=%temp%\%~n0.vbs
    echo >"%TempVbs%" d=DateAdd("d",-%KeepDays%,Now)
    echo >>"%TempVbs%" WScript.Echo Year(d) ^& Right(100+Month(d),2) ^& Right(100+Day(d),2)

    rem Execute vbscript and get file date - keep days (in YYYYMMDD format)
    for /F "tokens=*" %%A in ('cscript //nologo "%TempVbs%"') do set KeepDate=%%A
    if exist "%TempVbs%" del "%TempVbs%"
    exit /b

:ProcessFolder [Folder-Path]
    REM Prepare the input folder name for WMIC usage (split out drive letter, and change "\" to "\\")
    for /f "tokens=1* delims=:" %%A in ("%~1") do (
        set WmicDrive=%%~A:
        set WmicPath=%%~B
    )
    if "!WmicPath:~-1!" NEQ "\" set WmicPath=!WmicPath!\
    set WmicPath=!WmicPath:\=\\!

    REM Use WMIC DATAFILE to look for files in the date range of the prior month (remove carraige return from WMIC output lines)
    for /f "usebackq skip=2 tokens=2,3 delims=," %%A in (`WMIC DATAFILE Where "Drive='!WmicDrive!' AND Path='!WmicPath!' AND LastModified<'%KeepDate%'" GET LastModified^,Name^,Version /Format:csv 2^>NUL`) do (
        set LastModified=%%A

        set yyyy=!LastModified:~0,4!
        set mm=!LastModified:~4,2!
        
        REM Move file to "%ArchiveFolder%\YYYY\MM-YYYY" folder (create if needed)
        set DestDir=%ArchiveFolder%\!yyyy!\!mm!-!yyyy!
        if not exist "!DestDir!\" md "!DestDir!"
        move "%%~B" "!DestDir!">NUL
        echo.Moved "%%~B" to "!DestDir!">>"%LogFile%"
    )
    exit /b

Open in new window


I don't understand why it works in my machine and it doesn't on my VM.

Here is the message that I got when I launch it from the VM:

C:\Users\User\Desktop\L\Commands\Cmd-Ps\29154852_move-files-in-monthly-folders>for /F "usebackq skip=2 tokens=2,3 delims=," %A in (`WMIC DAT
 AND LastModified<'CScript Error: Execution of the Windows Script Host failed. (Access is denied. )'" GET LastModified,Name,Version /Format:csv 2>
set LastModified=%A
 set yyyy=!LastModified:~0,4!
 set mm=!LastModified:~4,2!
 REM Move file to "C:\Users\User\Desktop\L\Commands\Cmd-Ps\29154852_move-files-in-monthly-folders\Archive\YYYY\MM-YYYY" folder (create if ne
 set DestDir=C:\Users\User\Desktop\L\Commands\Cmd-Ps\29154852_move-files-in-monthly-folders\Archive\!yyyy!\!mm!-!yyyy!
 if not exist "!DestDir!\" md "!DestDir!"

Open in new window

If you have advice, please let me know
Thank you in advance for your help.
SOLUTION
Avatar of Bill Prew
Bill Prew

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Avatar of Luis Diaz

ASKER

Thank you Bill.

From the VM where it doesn't work:
User generated imageFrom the machine where it works:
User generated image
Avatar of slightwv (䄆 Netminder)
slightwv (䄆 Netminder)

Any reason you have to use BAT?  Especially BAT that needs CScript.  Powershell typically has much better ways to do things.

I'm not sure about your exact requirements and what you are trying to do but this seems close:
https://www.reddit.com/r/PowerShell/comments/7vbjpl/powershell_move_files_to_folder_by_date_modified/
@slightwv (䄆 Netminder):

Powershell can do this task the problem is that I want to exclude from the move some files based on a KeepDays variable. The idea is the following:
if KeepDays=2 that means that only files older than two days will be moved.
If there is another way to perform this without using cscript I can test it.

Thank you for your help.
ASKER CERTIFIED SOLUTION
Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
You can easily exclude files older than 2 days with a simple tweak from:
https://www.pdq.com/blog/using-get-childitem-find-files/


In the script from the link I posted
change:
$Files = Get-ChildItem -Path $Path

to:
$Files = Get-ChildItem -Path $Path | Where-Object {$_.LastWriteTime -gt (Get-Date).AddDays(-2)}
@Bill: Indeed, VM is managed by GPO, I am going to contact IT to see how I can manage this.
In the meantime, is there a way to exclude the KeepDay variable and just have a proposal to move all files from SourceFolder into MonthlyFolder based on ModifiedDate with two subfolders levels: YYYY>YYYY-MM
Example: 2019>2019-11
SOLUTION
Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Noted Bill, thank you for your help.