[solved]One batch file, two computers, two different results

Discussion forum for all Windows batch related topics.

Moderator: DosItHelp

Post Reply
Message
Author
Vmeskers
Posts: 2
Joined: 13 Feb 2013 22:30

[solved]One batch file, two computers, two different results

#1 Post by Vmeskers » 13 Feb 2013 22:54

Hi, I hope somebody can help.
I have been making a daily local back up of a shared folder for some time on computer1 (XP), now I want use to use computer2 (XP) to make this backup.

I have copied the batch file and the result (changed only the destination a bit), but the outcome is different:

Where on computer1, the backup was copied to a weekday folder

e:\backup\Thu (which is the correct procedure)

Now it makes a new folder like this:

e:\backup\14\2013 (not good)

The code is as follows:
[*]ECHO OFF
set source=z:\
set destination=e:\backup\
FOR /F "TOKENS=1* DELIMS= " %%A IN ('DATE/T') DO SET day=%%A
robocopy %source% %destination%%day% /mir /R:2 /W:5[*]

Hope somebody can help me out a) why this happens, b) what to do to get it working correctly again...

Thanks in advance.
Last edited by Vmeskers on 14 Feb 2013 01:44, edited 1 time in total.

foxidrive
Expert
Posts: 6031
Joined: 10 Feb 2012 02:20

Re: One batch file, two computers, two different results

#2 Post by foxidrive » 13 Feb 2013 22:59

Change the regional settings on the 2nd PC to match the first one - under date formats.

That changes the format when you use the DATE /T command and %date% variable.

abc0502
Posts: 1007
Joined: 26 Oct 2011 22:38
Location: Egypt

Re: One batch file, two computers, two different results

#3 Post by abc0502 » 13 Feb 2013 23:05

you can also use this instead, it is safer ( look at the day variable )

Code: Select all

@ECHO OFF
SET "Source=z:\"
SET "Destination=e:\backup\"
SET "Day=%date:~0,3%"
Robocopy "%source%" "%destination%%day%" /mir /R:2 /W:5

%date:~0,3% take the characters from index 0 and stop befor reaching index 3 that mean it just take the day name from this
Thu 02/14/2013

foxidrive
Expert
Posts: 6031
Joined: 10 Feb 2012 02:20

Re: One batch file, two computers, two different results

#4 Post by foxidrive » 13 Feb 2013 23:38

Or don't use basic commands to get parts of dates from because they vary with computer settings.

Try this - I assume you wanted the day in Thu format.

Code: Select all

  :: get day of week using WSH
  @echo off
  set TmpFile="%temp%.\tmp.vbs"
  echo> %TmpFile% n=Now
  echo>>%TmpFile% Wscript.Echo "set day="  + WeekDayName(Weekday(n),1)
  echo>>%TmpFile% Wscript.Echo "set day2=" + WeekDayName(Weekday(n))
  cscript //nologo "%temp%.\tmp.vbs" > "%temp%.\tmp.bat"
  call "%temp%.\tmp.bat"
  del  "%temp%.\tmp.bat"
  del  %TmpFile%
  set TmpFile=
  echo %day%
  echo %day2%

pause

mfm4aa
Posts: 70
Joined: 13 Feb 2013 14:02
Location: Europe

Re: One batch file, two computers, two different results

#5 Post by mfm4aa » 14 Feb 2013 00:59

I get this from my system:

Code: Select all

C:\Test>echo %date%
14.02.2013

C:\Test>date /t
14.02.2013


Is there no way to get the day of week in pure batch?

abc0502
Posts: 1007
Joined: 26 Oct 2011 22:38
Location: Egypt

Re: One batch file, two computers, two different results

#6 Post by abc0502 » 14 Feb 2013 01:09

does wmic run on your system, try executing this command in your two PC and see if you get it to work:
WMIC /?
if it works, we can find something there

foxidrive
Expert
Posts: 6031
Joined: 10 Feb 2012 02:20

Re: One batch file, two computers, two different results

#7 Post by foxidrive » 14 Feb 2013 01:36

mfm4aa wrote:I get this from my system:

Code: Select all

C:\Test>echo %date%
14.02.2013

C:\Test>date /t
14.02.2013


Is there no way to get the day of week in pure batch?


Not that I know of, if your region settings don't include the day. You would need to query the registry at the very least, or use an ascii binary in a 32 bit OS which can be embedded into the batch file.
WMIC and Powershell and VBS are reliable and work in any region.

I guess you could calculate how many days it has been since 1980-01-01 and figure out which day it is from that.

Vmeskers
Posts: 2
Joined: 13 Feb 2013 22:30

Re: One batch file, two computers, two different results

#8 Post by Vmeskers » 14 Feb 2013 01:42

foxidrive wrote:Or don't use basic commands to get parts of dates from because they vary with computer settings.

Try this - I assume you wanted the day in Thu format.

Code: Select all

  :: get day of week using WSH
  @echo off
  set TmpFile="%temp%.\tmp.vbs"
  echo> %TmpFile% n=Now
  echo>>%TmpFile% Wscript.Echo "set day="  + WeekDayName(Weekday(n),1)
  echo>>%TmpFile% Wscript.Echo "set day2=" + WeekDayName(Weekday(n))
  cscript //nologo "%temp%.\tmp.vbs" > "%temp%.\tmp.bat"
  call "%temp%.\tmp.bat"
  del  "%temp%.\tmp.bat"
  del  %TmpFile%
  set TmpFile=
  echo %day%
  echo %day2%

pause


Hi Foxidrive,

This is the solution! It is working like a charm (at least for me) !!!
Thanks a lot.

mfm4aa
Posts: 70
Joined: 13 Feb 2013 14:02
Location: Europe

Re: One batch file, two computers, two different results

#9 Post by mfm4aa » 14 Feb 2013 02:39

foxidrive wrote:I guess you could calculate how many days it has been since 1980-01-01 and figure out which day it is from that.

But imo there is no safe way to get a valid current date without the help of external programs. The user can set %date% to whatever he wants, e.g. "14.02.2013 Thu" or "02-14". %date% is always only a string.

The best code I found to get the day of the week is the use of robocopy itself:

Code: Select all

for /f "tokens=3" %i in ('robocopy /?^|find "Started"') do @echo %i
Last edited by mfm4aa on 14 Feb 2013 03:51, edited 1 time in total.

foxidrive
Expert
Posts: 6031
Joined: 10 Feb 2012 02:20

Re: One batch file, two computers, two different results

#10 Post by foxidrive » 14 Feb 2013 03:48

mfm4aa wrote:The best code I found to get the day of the week is the use of robocopy itself:

Code: Select all

for /f "tokens=3" %i in ('robocopy /?^|find "Started"') do @echo %i


That's a good tip. It won't work on XP though as Robocopy is only installed by default on Vista and later.

Squashman
Expert
Posts: 4488
Joined: 23 Dec 2011 13:59

Re: [solved]One batch file, two computers, two different res

#11 Post by Squashman » 14 Feb 2013 06:54

I like the Robocopy trick. Another one of those moments in time when you say to yourself "Why didn't I think of that.!"

Antonio posted some pure batch solutions over on StackOverFlow. The last one looks to be pure batch and independent of the regional settings.
http://stackoverflow.com/questions/1136 ... f-the-week

mfm4aa
Posts: 70
Joined: 13 Feb 2013 14:02
Location: Europe

Re: [solved]One batch file, two computers, two different res

#12 Post by mfm4aa » 14 Feb 2013 09:07

Squashman wrote:Antonio posted some pure batch solutions over on StackOverFlow. The last one looks to be pure batch and independent of the regional settings.
http://stackoverflow.com/questions/1136 ... f-the-week

This "date<nul" trick is not independent of the local settings, e.g.

Code: Select all

C:\Test>for /f "tokens=*skip=4" %a in ('reg query "HKCU\Control Panel\International" /v sShortDate') do @echo [%a]
[sShortDate     REG_SZ  MM.dd]

C:\Test>for /F "skip=1 tokens=2-4 delims=(-/)" %A in ('date ^< NUL') do @echo [%A] [%B] [%C]
[MM] [TT] [JJ]

C:\Test>for /F "tokens=1-3 delims=/" %a in ("%date%") do @echo [%a] [%b] [%c]
[02.14] [] []


but writing in the registry works:

Code: Select all

REM save the sShortDate setting
for /f "tokens=2*skip=4" %%a in ('reg query "HKCU\Control Panel\International" /v sShortDate') do set "ssShortDate=%%b"

REM set the sShortDate setting to dow
reg add "HKCU\Control Panel\International" /f /v sShortDate /d "ddd" >nul
set "dow=%date%"

REM restore the sShortDate setting
reg add "HKCU\Control Panel\International" /f /v sShortDate /d "%ssShortDate%" >nul
echo %dow%

.. if the batch has the rights to write there.

carlsomo
Posts: 91
Joined: 02 Oct 2012 17:21

Re: [solved]One batch file, two computers, two different res

#13 Post by carlsomo » 19 Feb 2013 23:59

This routine works in pure batch with all english date settings and non pure batch in foreign ones:

Code: Select all

@echo off&SetLocal EnableDelayedExpansion&goto :start or :English is faster on US machine
:GetDate [EnVar] [/s]
echo.GetDate [EnVar] Sets date into environment variable, EnVar as: mm-dd-yyyy
echo.Usage: GetDate mdy^&set ymd=%%errorlevel%%, ^(use %% rather than ^^! in command line)
echo.Usage: GetDate mdy^&set ymd=^^!errorlevel^^!, ^(use ^^! rather than %% in script^)
echo.If no argument passed it echo's the date in mm-dd-yyyy format
echo.Returns yyyymmdd in errorlevel regardless if Envar is passed as argument or not
echo.Works on NT/2K/XP/Vista/Win7 machines independent of most regional date settings
echo.If '/s' parameter is passed then EnVar_??? will set all individual date parameters...
echo.For example 'EnVar_dow' would be set to Tuesday on a Tuesday, ie. 'Envar_mon' is Feb
EndLocal&exit /b

:start
for /f "tokens=3" %%L in ('reg query "hklm\system\controlset001\control\nls\language" /v Installlanguage') do (
  if /i %%L equ 0409 goto :English
)

:wmic
set p1=%~1&if /i "!p1!" equ "/?" goto :GetDate
set setdate=%~2&if /i "!setdate!" equ "/s" set "setdate=true"
for /f "usebackq skip=1 tokens=1* delims=." %%a in (`"wmic OS Get localdatetime"`) do set ymd=%%a&goto :next
:next
set yy=%ymd:~0,4%&set mm=%ymd:~4,2%&set dd=%ymd:~6,2%&set ymd=%ymd:~0,8%
if defined p1 (
  Endlocal
  if /i "%setdate%" equ "true" call set_date %~1 %mm%-%dd%-%yy%
  call set "%~1=%mm%-%dd%-%yy%"&exit /b %yy%%mm%%dd%
)
EndLocal&echo.%mm%-%dd%-%yy%&exit /b %yy%%mm%%dd%

:English DOS version
set p1=%~1&if /i "!p1!" equ "/?" goto :GetDate
set setdate=%~2&if /i "!setdate!" equ "/s" set "setdate=true"
for /f "skip=1 tokens=2-4 delims=(-)" %%a in ('date^<nul') do (
  for /f "tokens=1-3 delims=.-/ " %%d in ("%date:* =%") do (
    set %%a=%%d&set %%b=%%e&set "%%c=%%f"
  )
)
if /i "%mm:~0,1%" gtr "9" call :month_convert mm
if /i 1%mm% lss 20 set "mm=0%mm%"
if /i %yy% lss 100 set "yy=20%yy%"
if defined p1 (
  Endlocal
  if /i "%setdate%" equ "true" call set_date %~1 %mm%-%dd%-%yy%
  call set "%~1=%mm%-%dd%-%yy%"&exit /b %yy%%mm%%dd%
)
EndLocal&echo.%mm%-%dd%-%yy%&exit /b %yy%%mm%%dd%

:month_convert
set "months=Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec"
call set "month=%%%~1%%"
set/a mnum=0
for %%m in (%months%) do set/a mnum+=1&if /i %month% equ %%m call set "%~1=!mnum!"&exit /b


optional Set_Date program will set all the relevant date parameters in one swoop to use at will:

Code: Select all

@echo off&goto :start
:Set_Date DateEnv [Date] or [/g="Prompt for Date: "]
echo.Usage: Set_Date.cmd DateEnv [Date] or [/g="Prompt for Date: "]
echo.Accepted date formats: m-d-y, m/d/y, yyyymmdd or 7 digit julian date
echo.DateEnv, if passed alone must be a defined date variable
echo.Returns 0 in errorlevel if the date is valid, else non-zero
echo.
echo.If DateEnv is valid or if [Date] is passed DateEnv_??? will be set to:
echo.DateEnv_mdy will be set to mm-dd-yyyy
echo.DateEnv_ymd will be set to yyyymmdd
echo.DateEnv_jul will be set to the 7 digit Julian date
echo.DateEnv_dow will be set to day of week, ie. Monday, Tuesday, etc.
echo.DateEnv_vrb will be set to Verbose Date, ie. Saturday, August 20th, 2011
echo.DateEnv_dd will be set to the 2 digit day
echo.DateEnv_mm will be set to the 2 digit month
echo.DateEnv_yyyy will be set to the 4 digit year
echo.DateEnv_mon will be set to 3 letter month, ie. Jan or Aug
echo.
echo.DateEnv itself will not be changed regardless if valid date or not
echo.Also formats yyyymmdd or 7 digit julian date input to desired output
echo.Example: Set_Date today %%date%% or Set_Date newyear 1/1/11
echo.Finally:
echo.If /g is passed as 2nd argument then quoted 3rd argument will prompt for date
echo.Example: Set_Date birthday /g="Enter your birth date: "
echo.         ECHO You were born on a %%birthday_dow%%
echo.If the '/g' option is used then the _GetString.cmd routine must be in the PATH
exit /b 1

:start
set "jul="
if [%1]==[] exit /b 255
if /i %~1 equ /? goto :Set_Date Syntax
SetLocal EnableDelayedExpansion
if defined %~1 (call set jul=%%%~1%%) else (
  if [%~2]==[] exit /b 255
)
if not [%~2]==[] (
  set "jul=%~2"
  set "args="%~3""
)
if /i %jul% equ /g (
  call _GetString %args% jul /d
  if !errorlevel! gtr 0 goto :BadDate
)
set mdy=%jul:/=%
set mdy=%mdy:-=%
if /i %mdy% equ %jul% (
  call :strlen %mdy%
  if /i !errorlevel! equ 7 (
    call :date_cvt mdy /j
  ) else (call :date_cvt jul /j)
) else (call :date_cvt jul /j)
if /i %errorlevel% equ 0 (
  set/a mdy=%jul%
  set/a dow=%jul% %% 7&call :set_day dow
) else (goto :BadDate)
call :date_cvt mdy /j
set "vrb=%mdy%"
call :format_verbose vrb dow mon
set/a ymd=%errorlevel%
Endlocal&(
  call set %~1_mdy=%mdy%&call set %~1_ymd=%ymd%&call set %~1_jul=%jul%
  call set %~1_vrb=%vrb%&call set %~1_dow=%dow%&call set %~1_dd=%ymd:~-2%
  call set %~1_mm=%mdy:~0,2%&call set %~1_yyyy=%ymd:~0,4%
  call set %~1_mon=%mon%&call set %~1_yy=%ymd:~2,2%
  exit /b 0
)
:BadDate
Endlocal&call set %~1_mdy=&call set %~1_ymd=&call set %~1_jul=^
&call set %~1_vrb=&call set %~1_dow=&exit /b %errorlevel%

::**********************************::
::*******||  SUBROUTINES   ||*******::
::**********************************::

:set_day
SetLocal&call set/a tkn=%%%~1%%+1
for /f "tokens=%tkn%" %%a in ("Monday Tuesday Wednesday Thursday Friday Saturday Sunday") do (
  set "dayofwk=%%a"
)
EndLocal&call set %~1=%dayofwk%&exit /b 1

:Date_Cvt DateEnv [/Julian] Date_env is converted
if [%~1]==[] exit /b 1
SetLocal&call set mdy=%%%~1%%
set ech=&set "arg="
if not [%~2]==[] (set arg=%~2&set arg=!arg:~0,2!)
xcopy /d:%mdy% /h /l "%~f0" "%~f0\">nul 2>&1
if /i %errorlevel% equ 0 (
  for /f "tokens=1-3 delims=/- " %%a in ("%mdy%") do (
    set m=%%a&set d=%%b&set "y=%%c"
    if /i 1!m! lss 20 set "m=0!m!"
    if /i 1!d! lss 20 set "d=0!d!"
    if /i 1!y! lss 20 set "y=0!y!"
    if /i !y! lss 80 (set y=20!y!) else (if !y! lss 100 set y=19!y!)
    set "mdy=!m!-!d!-!y!"
  )
) else (
  set /a rc=1
  for /f "tokens=1-3 delims=0123456789" %%a in ("%mdy%") do set "rc=%%a"
  if /i !rc! neq 1 set /a err=2&goto :end
  call :strlen %mdy%
  if /i !errorlevel! gtr 8 set /a err=3&goto :end
)
set mdy=%mdy:/=-%
set ymd=%mdy:-=%
if %ymd%==%mdy% (
  call :strlen %ymd%
  set /a err=!errorlevel!
  if /i !err! equ 7 if /i [%arg%] equ [/j] (
    call :gdate %ymd%
    set /a ymd=!errorlevel!
    set /a err=8&set "arg="
  )
  if /i !err! neq 8 goto :end
  set mdy=!ymd:~4,2!-!ymd:~6,2!-!ymd:~0,4!&set "ech=!mdy!"
) else (
  set ymd=%ymd:~4,4%%ymd:~0,4%&set "ech=!ymd!"
)
xcopy /d:%mdy% /h /l "%~f0" "%~f0\">nul 2>&1
set /a err=%errorlevel%
if /i %err% neq 0 (set ech=)
if /i %err% equ 0 if /i [%arg%] equ [/j] (
  call :jdate %ymd%
  set /a ech=!errorlevel!
)
:end
EndLocal&call set "%~1=%ech%"&exit /b %err%

:Strlen Returns length of string in errorlevel
setlocal&set "#=%*"
if not defined # exit /b 0
set/a len=0
:loop
set/a len+=1
set "#=!#:~1!"&if not defined # endlocal&exit/b %len%
goto :loop

:jdate
SetLocal
set yyyymmdd=%1
set yyyy=%yyyymmdd:~0,4%
set mm=%yyyymmdd:~4,2%
set dd=%yyyymmdd:~6,2%
if %mm:~0,1% equ 0 set mm=%mm:~1%
if %dd:~0,1% equ 0 set dd=%dd:~1%
set /a Month1=(%mm%-14)/12
set /a Year1=%yyyy%+4800
set /a JDate=1461*(%Year1%+%Month1%)/4+367*(%mm%-2-12*%Month1%)^
             /12-(3*((%Year1%+%Month1%+100)/100))/4+%dd%-32075
EndLocal&exit /b %JDate%

:gdate
SetLocal
set /a p      = %1 + 68569
set /a q      = 4 * %p% / 146097
set /a r      = %p% - ( 146097 * %q% +3 ) / 4
set /a s      = 4000 * ( %r% + 1 ) / 1461001
set /a t      = %r% - 1461 * %s% / 4 + 31
set /a u      = 80 * %t% / 2447
set /a v      = %u% / 11
set /a GYear  = 100 * ( %q% - 49 ) + %s% + %v%
set /a GMonth = %u% + 2 - 12 * %v%
set /a GDay   = %t% - 2447 * %u% / 80
if /i 1%GMonth% lss 20 set GMonth=0%GMonth%
if /i 1%GDay%   lss 20 set GDay=0%GDay%
set GDate=%GYear%%GMonth%%GDay%
EndLocal&exit /b %GDate%

:Format_Verbose M/D/Y dayofweek to verbose date
SetLocal&call set "dte=%%%~1%%"
set "dow=%%%~2%%"
set "st="
set "day=%dte:~3,2%"
set "mon=%dte:~0,2%"
set "year=%dte:~6,4%"
set "ymd=%year%%mon%%day%"
set "dy=%day:~1%"
if %day:~0,1% equ 0 set day=%day:~1%
if %mon:~0,1% equ 0 set mon=%mon:~1%
set months=January February March April May June^
 July August September October November December
for /f "tokens=%mon%" %%a in ("%months%") do set month=%%a
if /i %dy% equ 0 set st=th
if /i %dy% gtr 3 set st=th
if /i %day% geq 11 if /i %day% leq 13 set st=th
if defined st goto :end
set/a rst=%day% %% 10
for /f "tokens=%rst%" %%s in ("st nd rd") do set st=%%s
:end
set dow=%dow%, %month% %day%%st%, %year%
EndLocal&call set %~1=%dow%&call set %~3=%month:~0,3%&exit /b %ymd%

Post Reply