web-dev-qa-db-ja.com

Windowsバッチファイル変数を曜日に設定する

毎日実行されるWindowsバッチファイルがあります。データをファイルに記録し、ローテーションしたい(つまり、最大で過去7日間のデータがある).

コマンドDATEおよびDELIMSを調べました-解決策がわかりません。

曜日を含むファイル名を作成する簡単なソリューションはありますか?.

または、より良いシェルスクリプトに頼らなければなりませんか。

19
Ed Heal

%DATE%はあなたの友達ではありません。 %DATE%環境変数(およびDATEコマンド)は、完全に無限にカスタマイズ可能なWindows短い日付形式を使用して現在の日付を返すためです。 1人のユーザーが2012年6月6日を返すようにシステムを構成し、別のユーザーがFri060712を選択する場合があります。 %DATE%の使用は、BATプログラマにとって完全な悪夢です。

この問題を解決するには、2つの方法があります。

  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つの問題があります。

    • ローカルの特定の目的のためにグローバルレジストリ値を改ざんするため、同時に実行される場合を含め、短い日付形式で日付を照会する他のプロセスまたはユーザータスクに干渉する可能性があります。

    • また、システムまたはユーザーが異なると、ローカル言語で3文字の曜日を返します。

  2. WMIC Win32_LocalTimeを使用すると、FORコマンドで日付を直接解析するのに便利な方法で日付が返されます。

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

    これは私が推奨する方法です。

30
PA.

さらにいくつかの方法:

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マシンで動作します(ただし、小さな一時ファイルを作成します). 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(。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 [〜#〜]すでに回答として使用されていますが、完全なリファレンスが必要です。 そしてクリアされた<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);
13
npocmaka
@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などです。

6
Aacini

私の最初の答えは0から6までの数字として正しい曜日を与えると思った。しかし、あなたがnotを持っているので、この答えがあなたの望む結果をもたらさない理由を示したので、理由。

以下のバッチファイルは、名前に数字が含まれるログファイルを毎日作成します。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

これがあなたの望むものではない場合、私がそれを修正できるように問題を示してください。

[〜#〜] edit [〜#〜]:以下のバージョンは、ロケール設定に関係なく日付部分を取得します。

@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

[〜#〜] edit [〜#〜]:以下のバージョンでは、曜日を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

よろしく、

アントニオ

3
Aacini

最初-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%を使用する

2
Ted Waterbury

これは私の仕事ではなく(例から少し変更しました)、ゲームに遅れていますが、これは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

2
delliottg

これは私のために働く

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

これは私が最初に疑ったよりもはるかに複雑であることが判明し、それが私を魅了したものだと思います。

したがって、Visual Basic Sc​​riptを使用する代替ソリューションがあります。

バッチは、スクリプト(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

上記のバッチで唯一の注意点は、週の曜日が0〜6ではなく1〜7であることです。

2
David Kroukamp

私はこの解決策が私のために働いています:

Cmdファイルが配置されるのと同じディレクトリにdayOfWeek.vbsという名前のファイルを作成します。

dayOfWeek.vbsには1行が含まれます。

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
1
Manuel Alves

私はアメリカにいます。このコードは、Windows 7、Windows 2008 R2、Windows Server 2003、Windows XP(すべてのOSはWindows Updateおよびパッチで最新です)。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が含まれている長い日付形式に見える可能性があることです。

1
user2316634

ロケール依存バージョン:環境によっては、次のように日付から曜日名が抽出されます。

set dayname=%date:~0,3%

曜日名が%date%の最初の部分であると想定しています。ただし、マシンの設定によっては、サブストリング部分(~0,3)を変更する必要があります。

次のようなステートメントは、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%
1
Mark Wilkins

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
0
willstay

自分でこれを実行しようとしていて、空白行に関する苦情がありました:

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
)
0
georges
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 
0
Eamonn Deering

このトピックの別のスピン。以下のスクリプトは、現在の前後数日を曜日のプレフィックスで表示します。

コアにあるのは、日付をISO 8601規格(Mon == 0)で曜日を示すモジュロ7の値にエンコードするスタンドアロンの:dpackルーチンです。また、逆関数である:dunpkも提供されます。

@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
0
Paul Houle

私は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  
0
Omar