将 Windows 批处理文件变量设置为星期几



我有一个每天运行的Windows批处理文件。希望将数据记录到文件中并希望对其进行轮换(即最多拥有过去 7 天的数据)。

查看了命令DATEDELIMS - 无法找出解决方案。

有没有一个简单的解决方案来创建包含星期几的文件名,即 0 表示星期一等。

还是我必须求助于一些更好的 shell 脚本。

%DATE%不是你的朋友。因为 %DATE% 环境变量(和 DATE 命令)使用 Windows 短日期格式返回当前日期,该格式是完全且无限可自定义的。一个用户可以将系统配置为返回 07/06/2012,而另一个用户可以选择 Fri060712。使用 %DATE% 对于 BAT 程序员来说完全是一场噩梦。

有两种

可能的方法可以解决此问题:

  1. 您可能想通过将注册表值 HKCUControl PanelInternationalsShortDate 中的区域设置更改为可识别的格式来临时更改短日期格式。然后访问%DATE%以获取所需格式的日期;最后将格式恢复为原始用户格式。像这样的东西

    reg copy "HKCUControl PanelInternational" "HKCUControl PanelInternational-Temp" /f >nul
    reg add "HKCUControl PanelInternational" /v sShortDate /d "ddd" /f >nul
    set DOW=%DATE%
    reg copy "HKCUControl PanelInternational-Temp" "HKCUControl PanelInternational" /f >nul
    

    但是这种方法有两个问题:

    • 它篡改其本地特定目的的全局注册表值,因此它可能会干扰同时以短日期格式查询日期的其他进程或用户任务,包括同时运行时查询日期的自身。

    • 它以本地语言返回一周中的三个字母日,在不同的系统或不同的用户中可能有所不同。

  2. 使用
  3. WMIC Win32_LocalTime,它以方便的方式返回日期,以使用 FOR 命令直接对其进行分析。

    FOR /F "skip=1" %%A IN ('WMIC Path Win32_LocalTime Get DayOfWeek' ) DO (
      set DOW=%%A
    )
    

    这是我推荐的方法。

还有几种方法:

1.Robocopy在XP中不可用,但可以使用win 2003资源工具包下载。也可能取决于本地化:

@echo off
setlocal 
for /f "skip=8 tokens=2,3,4,5,6,7,8 delims=: " %%D in ('robocopy /l *   /ns /nc /ndl /nfl /np /njh /XF * /XD *') do (
 set "dow=%%D"
 set "month=%%E"
 set "day=%%F"
 set "HH=%%G"
 set "MM=%%H"
 set "SS=%%I"
 set "year=%%J"
)
echo Day of the week: %dow%
endlocal

2.MAKECAB - 适用于每台Windows机器(但创建一个小的临时文件)。卡洛斯提供的功能:

@Echo Off

Call :GetDate.Init
Rem :GetDate.Init should be called one time in the code before call to :Getdate
Call :GetDate
Echo weekday:%weekday%
Goto :EOF
:GetDate.Init
Set /A "jan=1,feb=2,mar=3,apr=4,may=5,jun=6,jul=7,aug=8,sep=9,oct=10,nov=11,dec=12"
Set /A "mon=1,tue=2,wed=3,thu=4,fri=5,sat=6,sun=7"
(
Echo .Set InfHeader=""
Echo .Set InfSectionOrder=""
Echo .Set InfFooter="%%2"
Echo .Set InfFooter1=""
Echo .Set InfFooter2=""
Echo .Set InfFooter3=""
Echo .Set InfFooter4=""
Echo .Set Cabinet="OFF"
Echo .Set Compress="OFF"
Echo .Set DoNotCopyFiles="ON"
Echo .Set RptFileName="NUL"
) >"%Temp%~foo.ddf"
Goto :Eof
:GetDate
Set "tf=%Temp%~%random%"
Makecab /D InfFileName="%tf%" /F "%Temp%~foo.ddf" >NUL
For /F "usebackq tokens=1-7 delims=: " %%a In ("%tf%") Do (
Set /A "year=%%g,month=%%b,day=1%%c-100,weekday=%%a"
Set /A "hour=1%%d-100,minute=1%%e-100,second=1%%f-100")
Del "%tf%" >NUL 2>&1
Goto :Eof

3.W32TM - 使用 Vista 中引入的命令开关,因此在 Windows 2003/XP 上不起作用:

@echo off
setlocal
call :w32dow day_ow
echo %day_ow%
pause
exit /b 0
endlocal
:w32dow [RrnVar]
setlocal
rem :: prints the day of the week
rem :: works on Vista and above

rem :: getting ansi date ( days passed from 1st jan 1601 ) , timer server hour and current hour
FOR /F "tokens=4,5 delims=:( " %%D in ('w32tm /stripchart /computer:localhost  /samples:1  /period:1 /dataonly /packetinfo^|find "Transmit Timestamp:" ') do (
 set "ANSI_DATE=%%D"
 set  "TIMESERVER_HOURS=%%E"
)
set  "LOCAL_HOURS=%TIME:~0,2%"
if "%TIMESERVER_HOURS:~0,1%0" EQU "00" set TIMESERVER_HOURS=%TIMESERVER_HOURS:~1,1%
if "%LOCAL_HOURS:~0,1%0" EQU "00" set LOCAL_HOURS=%LOCAL_HOURS:~1,1%
set /a OFFSET=TIMESERVER_HOURS-LOCAL_HOURS
rem :: day of the week will be the modulus of 7 of local ansi date +1
rem :: we need need +1 because Monday will be calculated as 0
rem ::  1st jan 1601 was Monday
rem :: if abs(offset)>12 we are in different days with the time server
IF %OFFSET%0 GTR 120 set /a DOW=(ANSI_DATE+1)%%7+1
IF %OFFSET%0 LSS -120 set /a DOW=(ANSI_DATE-1)%%7+1
IF %OFFSET%0 LEQ 120 IF %OFFSET%0 GEQ -120 set /a DOW=ANSI_DATE%%7+1

rem echo Day of the week: %DOW% 
endlocal & if "%~1" neq "" (set "%~1=%DOW%") else echo %DOW%

4..bat/jscript 混合(必须另存为 .bat):

 @if (@x)==(@y) @end /***** jscript comment ******
 @echo off
 for /f  %%d in ('cscript //E:JScript //nologo "%~f0"') do echo %%d
 exit /b 0
 *****  end comment *********/
 WScript.Echo((new Date).getDay());

5..bat/VBScript 混合(必须另存为 .bat)

 :sub echo(str) :end sub
echo off
'>nul 2>&1|| copy /Y %windir%System32doskey.exe '.exe >nul
'& echo/ 
'& for /f %%w in ('cscript /nologo /E:vbscript %~dpfn0') do echo day of the week %%w
'& echo/
'& del /q "'.exe" >nul 2>&1
'& exit /b
WScript.Echo Weekday(Date)
WScript.Quit

6.PowerShell可以从微软下载。默认情况下,在 win7 及更高版本的所有形式中可用:

@echo off
setlocal
for /f %%d in ('"powershell (Get-Date).DayOfWeek.Value__"') do set dow=%%d
echo day of the week : %dow%
endlocal

7.WMIC已经用作答案,但只是想有一个完整的参考。并清除<CR>

@echo off
setlocal
for /f "delims=" %%a in ('wmic path win32_localtime get dayofweek /format:list ') do for /f "delims=" %%d in ("%%a") do set %%d
echo day of the week : %dayofweek%
endlocal

9.自编译 jscript.net(必须保存为.bat):

@if (@X)==(@Y) @end /****** silent line that start jscript comment ******
@echo off
::::::::::::::::::::::::::::::::::::
:::       compile the script    ::::
::::::::::::::::::::::::::::::::::::
setlocal
if exist "%~n0.exe" goto :skip_compilation
set "frm=%SystemRoot%Microsoft.NETFramework"
:: searching the latest installed .net framework
for /f "tokens=* delims=" %%v in ('dir /b /s /a:d /o:-n "%SystemRoot%Microsoft.NETFrameworkv*"') do (
    if exist "%%vjsc.exe" (
        rem :: the javascript.net compiler
        set "jsc=%%~dpsnfxvjsc.exe"
        goto :break_loop
    )
)
echo jsc.exe not found && exit /b 0
:break_loop

call %jsc% /nologo /out:"%~n0.exe" "%~dpsfnx0"
::::::::::::::::::::::::::::::::::::
:::       end of compilation    ::::
::::::::::::::::::::::::::::::::::::
:skip_compilation
"%~n0.exe"
exit /b 0

****** end of jscript comment ******/
import System;
import System.IO;
var dt=DateTime.Now;
 Console.WriteLine(dt.DayOfWeek);
@ECHO OFF
REM GET DAY OF WEEK VIA DATE TO JULIAN DAY NUMBER CONVERSION
REM ANTONIO PEREZ AYALA
REM GET MONTH, DAY, YEAR VALUES AND ELIMINATE LEFT ZEROS
FOR /F "TOKENS=1-3 DELIMS=/" %%A IN ("%DATE%") DO SET /A MM=10%%A %% 100, DD=10%%B %% 100, YY=%%C
REM CALCULATE JULIAN DAY NUMBER, THEN DAY OF WEEK
IF %MM% LSS 3 SET /A MM+=12, YY-=1
SET /A A=YY/100, B=A/4, C=2-A+B, E=36525*(YY+4716)/100, F=306*(MM+1)/10, JDN=C+DD+E+F-1524
SET /A DOW=(JDN+1)%%7

道琼斯指数为0表示星期日,1表示星期一,依此类推。

我认为我的第一个答案给出了正确的星期几,作为 0 到 6 之间的数字。但是,由于您没有说明为什么此答案没有给出您想要的结果,因此我只能猜测原因。

下面的批处理文件每天创建一个日志文件,名称中有一个数字,0=星期日,1=星期一,等等......程序假定echo %date%以 MM/DD/YYYY 格式显示日期;如果不是这种情况,只需更改 for 命令中 mm 和 dd 变量的位置。

@echo off
for /F "tokens=1-3 delims=/" %%a in ("%date%") do set /A mm=10%%a %% 100, dd=10%%b %% 100, yy=%%c
if %mm% lss 3 set /A mm+=12, yy-=1
set /A a=yy/100, b=a/4, c=2-a+b, e=36525*(yy+4716)/100, f=306*(mm+1)/10, dow=(c+dd+e+f-1523)%%7
echo Today log data > Day-%dow%.txt

如果这不是您想要的,请指出问题,以便我修复它。

编辑:下面的版本获取独立于区域设置的日期部分:

@echo off
for /F "skip=1 tokens=2-4 delims=(-/)" %%A in ('date ^< NUL') do (
   for /F "tokens=1-3 delims=/" %%a in ("%date%") do (
      set %%A=%%a
      set %%B=%%b
      set %%C=%%c
   )
)
set /A mm=10%mm% %% 100, dd=10%dd% %% 100
if %mm% lss 3 set /A mm+=12, yy-=1
set /A a=yy/100, b=a/4, c=2-a+b, e=36525*(yy+4716)/100, f=306*(mm+1)/10, 
dow=(c+dd+e+f-1523)%%7
echo Today log data > Day-%dow%.txt

编辑:下面的版本将星期几插入为3个字母的短名称:

@echo off
for /F "skip=1 tokens=2-4 delims=(-/)" %%A in ('date ^< NUL') do (
   for /F "tokens=1-3 delims=/" %%a in ("%date%") do (
      set %%A=%%a
      set %%B=%%b
      set %%C=%%c
   )
)
set /A mm=10%mm% %% 100, dd=10%dd% %% 100
if %mm% lss 3 set /A mm+=12, yy-=1
set /A a=yy/100, b=a/4, c=2-a+b, e=36525*(yy+4716)/100, f=306*(mm+1)/10, 
dow=(c+dd+e+f-1523)%%7 + 1
for /F "tokens=%dow%" %%a in ("Sun Mon Tue Wed Thu Fri Sat") do set dow=%%a
echo Today log data > Day-%dow%.txt

问候

安东尼奥

结果比我最初怀疑的要复杂得多,我想这就是吸引我的原因,我搜索了每个地方,所有给出的方法都不适用于Windows 7。

所以我有一个使用Visual Basic Script的替代解决方案。

批处理创建并执行脚本(DayOfWeek.vbs),将脚本输出(星期一,星期二等)分配给一个变量(dow),然后检查该变量并分配另一个变量(dpwnum)与天数,然后删除VBS,希望它有所帮助:

@echo off
REM Create VBS that will get day of week in same directory as batch
echo wscript.echo WeekdayName(Weekday(Date))>>DayOfWeek.vbs
REM Cycle through output to get day of week i.e monday,tuesday etc
for /f "delims=" %%a in ('cscript /nologo DayOfWeek.vbs') do @set dow=%%a
REM delete vbs
del DayOfWeek.vbs
REM Used for testing outputs days name
echo %dow%
REM Case of the days name is important must have a capital letter at start
REM Check days name and assign value depending
IF %dow%==Monday set downum=0
IF %dow%==Tuesday set downum=1
IF %dow%==Wednesday set downum=2
IF %dow%==Thursday set downum=3
IF %dow%==Friday set downum=4
IF %dow%==Saturday set downum=5
IF %dow%==Sunday set downum=6
REM print the days number 0-mon,1-tue ... 6-sun
echo %downum%
REM set a file name using day of week number
set myfile=%downum%.bak
echo %myfile%
pause
exit

编辑:

虽然我转向 VBS,它可以纯批量完成,花了我一段时间才能让它工作并进行了大量搜索,哈哈,但这似乎有效:

 @echo off
SETLOCAL enabledelayedexpansion
SET /a count=0
FOR /F "skip=1" %%D IN ('wmic path win32_localtime get dayofweek') DO (
    if "!count!" GTR "0" GOTO next
    set dow=%%D
    SET /a count+=1
)
:next
echo %dow%
pause

在上述批次中,您唯一需要注意的是,它的星期几是从 1-7 而不是 0-6

这对

我有用

FOR /F "tokens=3" %%a in ('robocopy ^|find "Started"') DO SET TODAY=%%a

这不是我的工作(好吧,我从示例中稍微修改了一下),而且游戏已经很晚了,但这对我来说在 Server 2003 上有效;

@echo off  
set daysofweek=Monday,Tuesday,Wednesday,Thursday,Friday,Saturday,Sunday  
for /F "skip=2 tokens=2-4 delims=," %%A in ('WMIC Path Win32_LocalTime Get DayOfWeek /Format:csv') do set daynumber=%%A  
for /F "tokens=%daynumber% delims=," %%B in ("%daysofweek%") do set day=%%B

引自:技术支持论坛

我在美国。我可以在Windows 7,Windows 2008 R2,Windows Server 2003,Windows XP中运行此代码(所有操作系统都是最新的Windows更新和补丁)。所有这些都带有短日期设置,没有 ddd(或 dddd)(星期几)。

@echo off
for /f %%a in ('date /t') do set DAY=%%a
echo.
echo The Day Is: %DAY%
echo.

如果今天是星期四,它将输出"The Day Is: Thu"。

这将返回我测试过的所有 4 个 Windows 版本的日期。而且只有这一天。当我将短日期设置更改为"ddd,M/d/yyyy"时,我的输出会用逗号显示日期(例如 Thu),这告诉我此代码确实使用短日期格式。但也可能发生的是,如果短日期不包含星期几,它可能会查看长日期格式,在我测试的所有 4 台机器上,该格式都有 dddd。

First - Copy CON SETUPDAY.001 设置工作日=^Z(非常重要 - 无 cr/lf)

DATE /T >SETUPDAY.002
COPY SETUPDAY.001+SETUPDAY.002 NEWDAY.BAT >nul
CALL NEWDAY.BAT
SET WEEKDAY=%WORKDAY:~0,3%
SET MDY=%WORKDAY:~4,10%

在脚本中使用 %WEEKDAY%

依赖于区域设置的版本:在某些环境中,以下内容将从日期中提取日期名称:

set dayname=%date:~0,3%

它假定日期名称是%date%的第一部分。 但是,根据机器设置,子字符串部分(~0,3)需要更改。

像这样的语句会转储到具有三个字符的日期名称的文件:

set logfile=%date:~0,3%.log
echo some stuff > %logfile%

与区域设置无关的版本:如果您需要它对当前机器的日期格式的依赖性较小,另一种方法是编写一个打印星期几的微型应用程序。 然后使用批处理文件中该程序的输出。 例如,以下 C 应用程序打印 dayN其中 N=0..6。

#include <stdio.h>
#include <time.h>
int main( int argc, char* argv[] )
{
   time_t curtime;
   struct tm * tmval;
   time( &curtime );
   tmval = localtime( &curtime );
   // print dayN.  Or use a switch statement and print
   // the actual day name if you want
   printf( "day%d", tmval->tm_wday );
}

如果以上内容被编译并链接为 myday.exe ,那么您可以从批处理文件中使用它,如下所示:

for /f %%d in ('myday.exe') do set logfile=%%d.log
echo some stuff > %logfile%

我有这个解决方案为我工作:

在cmd文件所在的同一目录中创建一个名为dayOfWeek.vbs的文件。

dayOfWeek.vbs 包含一行:

wscript.stdout.write weekdayname(weekday(date))

或者,如果您想要日期数字而不是名称:

wscript.stdout.write weekday(date)

cmd 文件将包含以下行:

For /F %%A In ('CScript dayOfWeek.vbs //NoLogo') Do Set dayName=%%A

现在您可以使用变量 dayName,例如:

robocopy c:inetpub \DCStorage1Share1WebServerInetPub_%dayName% /S /XD history logs
<</div> div class="one_answers">

关于这个话题的另一个旋转。 下面的脚本显示当前几天,前缀为星期几。

核心是独立的 :d pack 例程,它将日期编码为一个值,该值的模数 7 根据 ISO 8601 标准 (Mon == 0) 显示星期几。 还提供了:d unpk,它是反函数:

@echo off& setlocal enabledelayedexpansion
rem 10/23/2018 daydate.bat: Most recent version at paulhoule.com/daydate
rem Example of date manipulation within a .BAT file.
rem This is accomplished by first packing the date into a single number.
rem This demo .bat displays dates surrounding the current date, prefixed
rem with the day-of-week.
set days=0Mon1Tue2Wed3Thu4Fri5Sat6Sun
call :dgetl y m d
call :dpack p %y% %m% %d%
for /l %%o in (-3,1,3) do (
  set /a od=p+%%o
  call :dunpk y m d !od!
  set /a dow=od%%7
  for %%d in (!dow!) do set day=!days:*%%d=!& set day=!day:~,3!
  echo !day! !y! !m! !d!
)
exit /b

rem gets local date returning year month day as separate variables
rem in: %1 %2 %3=var names for returned year month day
:dgetl
setlocal& set "z="
for /f "skip=1" %%a in ('wmic os get localdatetime') do set z=!z!%%a
set /a y=%z:~0,4%, m=1%z:~4,2% %%100, d=1%z:~6,2% %%100
endlocal& set /a %1=%y%, %2=%m%, %3=%d%& exit /b

rem packs date (y,m,d) into count of days since 1/1/1 (0..n)
rem in: %1=return var name, %2= y (1..n), %3=m (1..12), %4=d (1..31)
rem out: set %1= days since 1/1/1 (modulo 7 is weekday, Mon= 0)
:dpack
setlocal enabledelayedexpansion
set mtb=xxx  0 31 59 90120151181212243273304334& set /a r=%3*3
set /a t=%2-(12-%3)/10, r=365*(%2-1)+%4+!mtb:~%r%,3!+t/4-(t/100-t/400)-1
endlocal& set %1=%r%& exit /b

rem inverse of date packer
rem in: %1 %2 %3=var names for returned year month day
rem %4= packed date (large decimal number, eg 736989)
:dunpk
setlocal& set /a y=%4+366, y+=y/146097*3+(y%%146097-60)/36524
set /a y+=y/1461*3+(y%%1461-60)/365, d=y%%366+1, y/=366
set e=31 60 91 121 152 182 213 244 274 305 335
set m=1& for %%x in (%e%) do if %d% gtr %%x set /a m+=1, d=%d%-%%x
endlocal& set /a %1=%y%, %2=%m%, %3=%d%& exit /b

如果您可以将PC中的短日期格式更改为"ddd yyyy-MM-dd"(只有第一个参数"ddd"是必需的),则以下命令返回-

c:>vol | date
The current date is: Mon 2014-12-01

然后你可以写你的批处理文件 -

@echo off
vol | date | find /i "sun" > nul 
if not errorlevel 1 goto SUN
vol | date | find /i "mon" > nul 
if not errorlevel 1 goto MON
      # write block for other week days    
goto END
:SUN
set fname="sun"
goto BACKUP
:MON
set fname="mon"
goto BACKUP
      # write block for other week days
:BACKUP
echo %fname%
:END
Rem Remove the end comma and add /A to set for this line worked for me.
set /A a=yy/100, b=a/4, c=2-a+b, e=36525*(yy+4716)/100, f=306*(mm+1)/10 

我自己想这样做,看到关于空行的抱怨:

rem Make the win32_localtime output all one line, though some versions may contain blank lines as well.
rem So ignore blank lines and just pick up the number after the equal sign.
for /f "delims== tokens=2" %%a in ('wmic path win32_localtime get dayofweek /format:list') do (
    rem Increment the DOW as it is documented to be a zero-based index starting with Sunday.
    set /a DayOfWeekIndex=%%a+1
)
rem Also get name day of week. The DOW coming in is now a one-based index.
rem This is used to reference the "array" of week day names.
set DayOfWeekNames=Sun Mon Tue Wed Thu Fri Sat
for /f "tokens=%DayOfWeekIndex%" %%b in ("%DayOfWeekNames%") do (
    set DayOfWeekName=%%b
)

我改进了 Aacini 答案使它回声 一周中的一整天 名称

所以这是我的代码

@echo off
for /F "skip=1 tokens=2-4 delims=(-/)" %%A in ('date ^< NUL') do (
   for /F "tokens=1-3 delims=/" %%a in ("%date%") do (
      set %%A=%%a
      set %%B=%%b
      set %%C=%%c
   )
)
set /A mm=10%mm% %% 100, dd=10%dd% %% 100
if %mm% lss 3 set /A mm+=12, yy-=1
set /A a=yy/100, b=a/4, c=4-a+b, e=36525*(yy+4716)/100, f=306*(mm+1)/10,dow=(c+dd+e+f-1523)%%7 + 1
for /F "tokens=%dow%" %%a in ("Sunday Monday Tuesday Wednesday Thursday Friday Saturday ") do set dow=%%a
echo Today is %dow%>"Today is %dow%.txt"
echo Today is %dow%
Pause>Nul
REM Sun Mon Tue Wed Thu Fri Sat
REM Sunday Monday Tuesday Wednesday Thursday Friday Saturday  
<</div> div class="one_answers">

我使用 Tiny C 编写工作日.exe并使用批处理文件运行。

for /f %% in ('weekday.exe') do set weekday=%%i

平日.c

#include <time.h>
#include <stdio.h>

int main(int argc, char** argv) {
    time_t curtime;
    struct tm * tmval;
  
    time( &curtime );
    tmval = localtime( &curtime );

    if (tmval->tm_wday == 1) printf("Mon");
    if (tmval->tm_wday == 2) printf("Tue");
    if (tmval->tm_wday == 3) printf("Wed");
    if (tmval->tm_wday == 4) printf("Thu");
    if (tmval->tm_wday == 5) printf("Fri");
    if (tmval->tm_wday == 6) printf("Sat");
    if (tmval->tm_wday == 0) printf("Sun");
     return 0;
}

使用 MSHTA 和 javascript 的版本。将 %jsfunc% 更改为要调用的 jscript 函数

@echo off
::Invoke a javascript function using mhta
set jsfunc=new Date().getDay()
set dialog="about:<script>resizeTo(0,0);new ActiveXObject('Scripting.FileSystemObject').
set dialog=%dialog%GetStandardStream(1).WriteLine(%jsfunc%);close();</script>"
for /f "tokens=* delims=" %%p in ('mshta.exe %dialog%') do set ndow=%%p
::get dow string from array of strings  
for /f "tokens=%ndow%"  %%d in ("Mon Tue Wed Thu Fri Sat Sun") do set dow=%%d 
echo dow is : %ndow%  %dow%
pause

最新更新