batch-file

Batch script to generate folders for specific year month, week & weekday


Couple of a last days i´ve been searching for answer for this question. There is a lot of answers dealing with batch folder creation for whole year, but not enough specific so i would appreciate answer very much.

So i would like to have this kind of folder structure as it follows

2017 (for example main folder for year 2017)  
01_JAN....12_DEC (subfolders with names of month )  
01JAN/01_01_SUN, 02_01_MON, 03_01_TUE...etc  (subsub folders with week day name at the end)

also if its possible it would be fine to include also week numbers here too although i would be satisfied with week days ie

01JAN/01_01_SUN-52, 02_01_MON-01, 03_01_TUE-01...09_01_MON-02 etc with weekdays starts with monday

im planning to use this in project of automation of production of barcode

thank you!
p.s. closest i got was this example that i manage to found How do I write a batch script to generate folders for each month, day and year?


Solution

  • It is possible with pure batch and the help of several date functions from Ritchie Lawrence Batchfunctionlibrary published under the MIT License and other sources.

    Sample output created in 30 seconds on a ramdisk:
    EDIT Streamlined version with less calls and same output takes 8secs

    > tree a:\
    A:\
    ├───2017
    │   ├───01_Jan
    │   │   ├───01_01_Sun-52(2016)
    │   │   ├───02_01_Mon-01
    │   │   ├───03_01_Tue-01
    │   │   ├───04_01_Wed-01
    ...
    │   │   ├───30_01_Mon-05
    │   │   └───31_01_Tue-05
    │   ├───02_Feb
    │   │   ├───01_02_Wed-05
    │   │   ├───02_02_Thu-05
    ...
    

    And here the lengthy batch
    (change variable Base to contain your base folder):

    :: Q:\Test\2017\07\23\SO_45269929.cmd
    :: https://stackoverflow.com/questions/45269929/batch-script-to-generate-folders-for-specific-Year-month-and-day
    @Echo off&SetLocal EnableExtensions EnableDelayedExpansion
    Set "Base=C:\Test\2"
    Set "Year=%~1"
    If not defined Year Set /P "Year=Enter Year (4 places) yyyy :"
    
    :: To be more efficient get month/day nmaes array
    For %%A in (:01:Jan:Mon: :02:Feb:Tue: :03:Mar:Wed:  :04:Apr:Thu:
                :05:May:Fri:  :06:Jun:Sat: :07:Jul:Sun: :08:Aug::
                :09:Sep:: :10:Oct:: :11:Nov:: :12:Dec::
    ) do for /F "tokens=1-3 delims=:" %%l in ("%%A") do (
        set "MonN[%%l]=%%m"
        set "DayN[%%l]=%%n"
    )
    Call :DateToMJD %Year% 01 01 StartDate
    Call :DateToMJD %Year% 12 31 EndDate
    
    Echo [%date% %time%] Start creating folders for Year %Year%
    For /L %%M in (%StartDate%,1,%EndDate%) Do Call :GenDay %%M
    Echo [%date% %time%] Done  creating folders for Year %Year%
    Goto :Eof
    
    :GenDay
    Call :MJDToDate  %1 YY MM DD
    Call :DateToWeek %YY% %MM% %DD% yn cw dw
    Set "Folder=%Base%\%YY%\%MM%_!MonN[%MM%]!\%DD%_%MM%_!DayN[0%dw%]!-%cw%"
    If %YY% neq %yn% Set "Folder=%Folder%(%yn%)"
    MD "%Folder%"
    Goto :Eof
    :::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
    :DateToMJD %yy% %mm% %dd% MJD
    ::
    :: By:   Ritchie Lawrence, 2002-06-15. Version 1.0
    ::
    :: Func: Returns a Modified Julian Day (MJD) from a UTC date.
    ::       Reference date (day 0) is Wednesday 17th November 1858. For
    ::       NT4/2K/XP/2003.
    :: Args:
    ::  %1 Year component used to create MJD, 2 or 4 digits (by val)
    ::  %2 month component used to create MJD, leading zero ok (by val)
    ::  %3 day of month used to create MJD, leading zero ok (by val)
    ::  %4 var to receive MJD (by ref)
    :::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
    SetLocal EnableExtensions
    Set yy=%1&set mm=%2&set dd=%3
    if 1%yy% LSS 200 if 1%yy% LSS 170 (set yy=20%yy%) else (set yy=19%yy%)
    Set /a dd=100%dd%%%100,mm=100%mm%%%100
    Set /a z=14-mm,z/=12,y=yy+4800-z,m=mm+12*z-3,j=153*m+2
    Set /a j=j/5+dd+y*365+y/4-y/100+y/400-2432046
    Endlocal&set %4=%j%&Goto :Eof
    :::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
    :MJDToDate %MJD% yy mm dd
    ::
    :: By:   Ritchie Lawrence, 2002-06-15. Version 1.1
    :: Func:
    ::  Returns a UTC date from a Modified Julian Day (MJD). Reference
    ::  date (day 0) is Wednesday 17th November 1858. For NT4/2K/XP/2003.
    :: 
    :: Args: %1 MJD used to create calEndar date (by val)
    ::       %2 var to receive Year component, 4 digits (by ref)
    ::       %3 var to receive month component, 2 digits, 01-12 (by ref)
    ::       %4 var to receive day of month, 2 digits, 01-31 (by ref)
    :::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
    SetLocal EnableExtensions
    Set /a a=%1+2432045,b=4*a+3,b/=146097,c=-b*146097,c/=4,c+=a
    Set /a d=4*c+3,d/=1461,e=-1461*d,e/=4,e+=c,m=5*e+2,m/=153,dd=153*m+2
    Set /a dd/=5,dd=-dd+e+1,mm=-m/10,mm*=12,mm+=m+3,yy=b*100+d-4800+m/10
    (if %mm% LSS 10 set mm=0%mm%)&(if %dd% LSS 10 set dd=0%dd%)
    Endlocal&set %2=%yy%&set %3=%mm%&set %4=%dd%&Goto :Eof
    :::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
    :::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
    :DateToWeek %yy% %mm% %dd% yn cw dw
    ::
    :: By:   Ritchie Lawrence, Updated 2002-11-20. Version 1.1
    ::
    :: Func: Returns an ISO 8601 Week date from a calEndar date.
    ::       For NT4/2000/XP/2003.
    :: 
    :: Args: %1 Year component to be converted, 2 or 4 digits (by val)
    ::       %2 month component to be converted, leading zero ok (by val)
    ::       %3 day of month to be converted, leading zero ok (by val)
    ::       %4 var to receive Year, 4 digits (by ref)
    ::       %5 var to receive calEndar week, 2 digits, 01 to 53 (by ref)
    ::       %6 var to receive day of week, 1 digit, 1 to 7 (by ref)
    :::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
    SetLocal EnableExtensions
    Set yy=%1&set mm=%2&set dd=%3
    if 1%yy% LSS 200 if 1%yy% LSS 170 (set yy=20%yy%) else (set yy=19%yy%)
    Set /a dd=100%dd%%%100,mm=100%mm%%%100
    Set /a z=14-mm,z/=12,y=yy+4800-z,m=mm+12*z-3,Jd=153*m+2
    Set /a Jd=Jd/5+dd+y*365+y/4-y/100+y/400-32045
    Set /a y=yy+4798,Jp=y*365+y/4-y/100+y/400-31738,t=Jp+3,Jp=t-t%%7
    Set /a y=yy+4799,Jt=y*365+y/4-y/100+y/400-31738,t=Jt+3,Jt=t-t%%7
    Set /a y=yy+4800,Jn=y*365+y/4-y/100+y/400-31738,t=Jn+3,Jn=t-t%%7
    Set /a Jr=%Jp%,yn=yy-1,yn+=Jd/Jt,yn+=Jd/Jn
    if %Jd% GEQ %Jn% (set /a Jr=%Jn%) else (if %Jd% GEQ %Jt% set /a Jr=%Jt%)
    Set /a diff=Jd-Jr,cw=diff/7+1,wd=diff%%7,wd+=1
    if %cw% LSS 10 set cw=0%cw%
    Endlocal&set %4=%yn%&set %5=%cw%&set %6=%wd%&Goto :Eof
    :::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::