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

时间:2012-07-06 14:26:58

标签: windows scripting batch-file

我有一个每天运行的Windows批处理文件。希望将数据记录到文件中并希望将其旋转(即最多拥有最近7天的数据)。

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

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

或者我必须使用更好的shell脚本。

17 个答案:

答案 0 :(得分:28)

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

有两种方法可以解决这个问题:

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

    reg copy "HKCU\Control Panel\International" "HKCU\Control Panel\International-Temp" /f >nul
    reg add "HKCU\Control Panel\International" /v sShortDate /d "ddd" /f >nul
    set DOW=%DATE%
    reg copy "HKCU\Control Panel\International-Temp" "HKCU\Control Panel\International" /f >nul
    

    但这种方法有两个问题:

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

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

  2. 使用 WMIC Win32_LocalTime ,以方便的方式返回日期,使用FOR命令直接解析它。

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

    这是我推荐的方法。

答案 1 :(得分:13)

更多方法:

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机器(但会创建一个小的临时文件)。Function provided by carlos:

@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 hybrid (必须保存为.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 hybrid (must be saved as .bat)

 :sub echo(str) :end sub
echo off
'>nul 2>&1|| copy /Y %windir%\System32\doskey.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 可以从microsoft下载。默认情况下可以在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 已经用作答案,但只想获得完整的参考资料。And with cleared <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.NET\Framework\"
:: searching the latest installed .net framework
for /f "tokens=* delims=" %%v in ('dir /b /s /a:d /o:-n "%SystemRoot%\Microsoft.NET\Framework\v*"') do (
    if exist "%%v\jsc.exe" (
        rem :: the javascript.net compiler
        set "jsc=%%~dpsnfxv\jsc.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);

答案 2 :(得分:6)

@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

DOW为0表示星期日,1表示星期一等等。

答案 3 :(得分:3)

我认为我的第一个答案是将正确的星期几作为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

此致

安东尼奥

答案 4 :(得分:2)

这对我有用

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

答案 5 :(得分:2)

首先 - 复制CON SETUPDAY.001     SET WORKDAY = ^ 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%

答案 6 :(得分:2)

这不是我的工作(嗯,我从示例中稍微修改了一下),而且它在游戏的后期很晚,但这适用于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

引文:TechSupportForum

答案 7 :(得分:2)

事实证明这比我第一次怀疑的更复杂,我猜这是引起我兴趣的因素,我搜索了每一个地方,所有给出的方法都无法在Windows 7上运行。

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

批处理创建并执行脚本(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

答案 8 :(得分:1)

我在美国。我可以在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。

答案 9 :(得分:1)

与语言环境相关的版本:在某些环境中,以下内容将从日期中提取日期名称:

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%

答案 10 :(得分:1)

我有这个解决方案适合我:

在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 \\DCStorage1\Share1\WebServer\InetPub_%dayName% /S /XD history logs

答案 11 :(得分:0)

如果您可以将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

答案 12 :(得分:0)

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 

答案 13 :(得分:0)

我本人希望自己这样做并看到有关空白行的投诉:

    .sticky{ position: fixed;  top: 0;}

答案 14 :(得分:0)

我改进了Aacini Answer 使它成为Echo全天的名字

所以这是我的代码

@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  

答案 15 :(得分:0)

关于此主题的另一种旋转。下面的脚本显示当前日期周围的几天,并带有星期几前缀。

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

Acl              : <redacted>
Billing          : 
Cors             : 
DefaultObjectAcl : {, , }
Encryption       : 
ETag             : CAM=
Id               : find-seller-dev-billing-export-3
Kind             : storage#bucket
Labels           : 
Lifecycle        : 
Location         : AUSTRALIA-SOUTHEAST1
Logging          : 
Metageneration   : 3
Name             : find-seller-dev-billing-export-3
Owner            : Google.Apis.Storage.v1.Data.Bucket+OwnerData
ProjectNumber    : 770296747780
SelfLink         : https://www.googleapis.com/storage/v1/b/find-seller-dev-billing-export-3
StorageClass     : REGIONAL
TimeCreatedRaw   : 2018-10-24T01:29:48.750Z
TimeCreated      : 24/10/2018 2:29:48 p.m.
UpdatedRaw       : 2018-10-24T01:31:27.251Z
Updated          : 24/10/2018 2:31:27 p.m.
Versioning       : 
Website          : 

答案 16 :(得分:-1)

使用MSHTA和javascript的版本。将%jsfunc%更改为要调用的whateve 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