2

Currently i have a specific batch file i need to run every month. I would like to combine it into one bat file. with condition if its 1st of February use feb-19.

If current date is January 2019 run

copy "C:\TESTone\*.*" "C:\Jan-19"
move "C:\TESTone\*.*" "\\172.1.1.1\Shared-File\Jan-19\"

If current date is February 2019 run

copy "C:\TESTone\*.*" "C:\Feb-19"
move "C:\TESTone\*.*" "\\172.1.1.1\Shared-File\Feb-19\"

If current date is March 2019 run

copy "C:\TESTone\*.*" "C:\Mar-19"
move "C:\TESTone\*.*" "\\172.1.1.1\Shared-File\Mar-19\"
Compo
  • 36,585
  • 5
  • 27
  • 39
Higara
  • 21
  • 2
  • @catcat the destination folder is already pre created to Jan-19, Feb-19, ... etc – Higara Jan 07 '19 at 08:49
  • Well change it. One adapts to what is easy. – CatCat Jan 07 '19 at 08:55
  • `echo %Date:~10,4%%Date:~7,2%%Date:~4,2%` is what people actually do. – CatCat Jan 07 '19 at 09:03
  • Why would you want to pre-define each directory? that means each year you have to create 12 directories manually and change your script to accomodate for that. That is not even automating it. You could simply let the script create the directory each time if not exist and copy the files. Technically you never need to do any maintenance on the script again. – Gerhard Jan 07 '19 at 10:06
  • 1
    @CatCat `echo %Date:~10,4%%Date:~7,2%%Date:~4,2%` is not going to give the same result for everyone. System Dates differ depending on policies, locations, OS versions etc.. Mine for instance would echo `-0-0` – Gerhard Jan 07 '19 at 10:21
  • 1
    Of course using batch means you need to take into account regional differences. That is why using a NON programming language, like batch a computer operating language for users, is a bad idea. I'm not in America either, but that is the common region for programming languages. That's all I program in and the spelling of `colour` (correct English) always traps me - languages want `color`. – CatCat Jan 07 '19 at 10:25
  • Consider accepting an answer. – double-beep Feb 11 '19 at 18:46

3 Answers3

2

Here is a possible solution:

@echo off

setlocal EnableDelayedExpansion

set month[01]=Jan
set month[02]=Feb
set month[03]=Mar
set month[04]=Apr
set month[05]=May
set month[06]=Jun
set month[07]=Jul
set month[08]=Aug
set month[09]=Sep
set month[10]=Oct
set month[11]=Nov
set month[12]=Dec

for /f "tokens=2 delims==" %%A in ('wmic OS Get localdatetime /value') do set "dt=%%A"
set "YY=%dt:~2,2%" & set "MM=%dt:~4,2%"

copy "C:\TESTone\*.*" "C:\!month[%MM%]!-%YY%"
move "C:\TESTone\*.*" "\\172.1.1.1\Shared-File\!month[%MM%]!-%YY%\"
pause
  • Enabling delayed expansion will help here, since we will need it here, neither inside a code block nor using it when setting and using variable in one line. It will help since we want to echo a variable whose value is the name of another variable.
  • Setting array of months. We use form varname[monthnum].
  • Finding date requires wmic, else it won't be international the same. The date and time environment variables are defined by user and they usually depend on user regional settings.
  • Now, setting the last two digits of the year are stored into the YY variable and the two digits of the month are stored in MM variable.
  • The command that OP wanted was copy "C:\TESTone\*.*" "C:\MMM-YY" and move "C:\TESTone\*.*" "\\172.1.1.1\Shared-File\MMM-YY\". So, YY is just ready, we have:
copy "C:\TESTone\*.*" "C:\MMM-%YY%"
move "C:\TESTone\*.*" "\\172.1.1.1\Shared-File\MMM-%YY%\"

MMM is the value of variables month[MM]. So, using here delayed expansion; wrapping number variables with ! and MM with %. It will be:

copy "C:\TESTone\*.*" "C:\!month[%MM%]!-YY"
move "C:\TESTone\*.*" "\\172.1.1.1\Shared-File\!month[%MM%]!-YY\"

and then:

copy "C:\TESTone\*.*" "C:\!month[num]!-YY"
move "C:\TESTone\*.*" "\\172.1.1.1\Shared-File\!_num!-YY\"

and then being processed which is actually what OP requested.

double-beep
  • 5,031
  • 17
  • 33
  • 41
  • 2
    Just a small observation... Why do you use the "strange" `set _01=Jan` notation to define the _array_ of month names? You may also use the _standard_ `set month[01]=Jan` one that is much clearer! IMHO beginners needs clear and simple answers, particularly in the case of Batch files that are intrinsically unclear... Why insert an additional complexity when the simple answer exists? I invite you to read [this post](https://stackoverflow.com/questions/10544646/dir-output-into-bat-array/10569981#10569981)... – Aacini Jan 07 '19 at 12:53
  • BTW the `copy "C:\TESTone\*.*" "C:\!_MM!-%YY%"` line _in the description_ missed the percent signs around `MM` variable, although the program code is correct... – Aacini Jan 07 '19 at 13:05
  • I would initialized the month array this way: `set m=100 & for %%a in (Jan Feb ... Dec) do set /A "m+=1" & set "month[!m:~1!]=%%a"` – Aacini Jan 13 '19 at 02:00
2

An alternative to wmic in getting a locale/user settings independent date is powershell,
which can directly output the desired format:

:: Q:\Test\2019\01\07\SO_54070456.cmd
@Echo off
for /f "usebackq" %%A in (`powershell -NoP -C "get-date -f 'MMM-yy'"`) Do set "Month=%%A"
copy "C:\TESTone\*.*" "C:\%Month%"
move "C:\TESTone\*.*" "\\172.1.1.1\Shared-File\%Month%\"

Here the only echoed resulting commands:

> Q:\Test\2019\01\07\SO_54070456.cmd
copy "C:\TESTone\*.*" "C:\Jan-19"
move "C:\TESTone\*.*" "\\172.1.1.1\Shared-File\Jan-19\"

PowerShell will return the month abbreviation MMM with the current culture, to select a special deviating culture use:

(Get-Date).ToString('MMM-yy',(New-Object System.Globalization.CultureInfo("en-us")))

To find a culture you might use the .dot Net function:

[globalization.cultureinfo]::GetCultures('allCultures')

  • Out of curiosity, why are you using always PowerShell in tasks? It is neither requested not rejected in this case. The problem is that as the script will run after every user login, it will take some time due to PowerShell load. I also think that the code is incorrect. The output depends heavily on language settings. Running `powershell -NoP -C "get-date -f 'MMM-yy'"` produces me `Ιαν-19`. – double-beep Jan 07 '19 at 16:47
  • Well the wording `locale independent` might be unlucky in this case. But you'll usually want the month names **in your** locale. If you need a specififc one that's not a problem `(Get-Date).ToString('MMM-yy',(New-Object System.Globalization.CultureInfo("en-us")))`.The reason why I like to combine batch and powershell simply is I do like both and PowerShell has benefits in calculating dates, file editing, selecting and grouping especially objects. @double-beep –  Jan 07 '19 at 17:59
  • Much better. You can [edit] your answer including it. – double-beep Jan 07 '19 at 18:01
  • @double-beep Just to find out `[globalization.cultureinfo]::GetCultures('allCultures')|sls 'gr'` and `(Get-Date).ToString('MMM-yy',(New-Object System.Globalization.CultureInfo("el-GR")))` –  Jan 07 '19 at 18:11
0

Depending in your regional settings you may need to change a little bit some of the parameters on the set destFolder=!month:~%d%,3!-%date:~8,2%, it is because that I insert an echo to show you on screen first what is happening. Also a pause at the end. Once debugged, you can remove the pause:

@echo off
setlocal EnableDelayedExpansion
for /F "tokens=1 delims=/" %%m in ("%date%") do (
   set /A "m=(1%%m%%100-1)*3"
)
set month=JanFebMarAprMayJunJulAugSepOctNovDec
set destFolder=!month:~%d%,3!-%date:~8,2%

set destFolder1=C:\%destFolder%\
echo copy "C:\TESTone\*.*" %destFolder1%
copy "C:\TESTone\*.*" %destFolder1%

set destFolder2=\\172.1.1.1\Shared-File\%destFolder%\
echo move "C:\TESTone\*.*" %destFolder2%
move "C:\TESTone\*.*" %destFolder2%

pause
Gerhard
  • 22,678
  • 7
  • 27
  • 43
Angel M.
  • 1,360
  • 8
  • 17
  • You need to use `wmic` also, to make your solution work for all. For example for me, it is not working. Also, where `%d%` variable is defined? – double-beep Jan 07 '19 at 09:10
  • @double-beep: Good to know !!! Yes, your solution is more accurate. I have a new tip now. Thanks – Angel M. Jan 07 '19 at 09:40