0

Problem: I have files stored in C:\Payment List. The file types are different and their timestamps are different too. I want to group files in the folder such that they are in a parent folder according to the year the file was created. In that parent folder year, I want the files to be grouped into a subfolder called month according to the month the files were created. In the subfolder month I want the files to be grouped into day according to the day the files were created. Below is the script I have

@echo off

rem Change this directory to the folder with the files
cd "C:\Payment List"

rem Loop through all files in the folder
for %%f in (*) do (
    rem Extract the year, month, and day from the file timestamp
    set "YEAR=%%~tf:~6,4"
    set "MONTH=%%~tf:~3,2"
    set "DAY=%%~tf:~0,2"
    
    rem Create the necessary subfolders
    if not exist "%YEAR%" md "%YEAR%"
    if not exist "%YEAR%\%MONTH%" md "%YEAR%\%MONTH%"
    if not exist "%YEAR%\%MONTH%\%DAY%" md "%YEAR%\%MONTH%\%DAY%"
    
    rem Move the file to the subfolder
    move "%%f" "%YEAR%\%MONTH%\%DAY%"
)
pause

Unfortunately when I run this script I get the error:

The filename, directory name, or volume label syntax is incorrect.
The filename, directory name, or volume label syntax is incorrect.
The specified path is invalid.
        0 file(s) moved.

Please help me script my script.

I expect the script to group all files in the folder according to the timestamp they were created. i.e a file from 1st may 2019 must be found in the folder 2019\05\01.

Compo
  • 36,585
  • 5
  • 27
  • 39
  • Further to @yacc soultion : The standard [delayed expansion trap link](https://stackoverflow.com/a/30284028/2128947). You could simply use `set "target=!stamp:~6,4!\!stamp:~3,2!\!stamp:~0,2!"` (quotes recommended) then `md "!target!" 2>nul` (which will create all intermediate directories; the `2>nul` suppresses any error-report (like "directory already exists")) – Magoo Apr 09 '23 at 03:21

1 Answers1

1

You cannot use the replace syntax on a parameter-style variable like %f. First store the value to a normal variable using SET.

setlocal EnableDelayedExpansion
for %%f in (*) do (
    rem Extract the year, month, and day from the file timestamp
    set STAMP=%%~tf
    set YEAR=!STAMP:~6,4!
    set MONTH=!STAMP:~3,2!
    set DAY=!STAMP:~0,2!

    rem Create folder and subfolder if not exists
    md !YEAR!\!MONTH!\!DAY! 2>nul

    rem Move the file to the subfolder
    move "%%f" !YEAR!\!MONTH!\!DAY!
)

You'll also have to activate delayed expansion. Otherwise the variables would be set before the loop is entered.

Perhaps you also want to prevent any folders you created to show up in the filelist, by using *.csv instead of *, say.

Edit: Suggestions from @Magoo included.

yacc
  • 2,915
  • 4
  • 19
  • 33