Установка переменной пакетного файла Windows на день недели

У меня есть пакетный файл Windows, который работает ежедневно. Пожелайте записывать данные в файл и хотите его повернуть (т.е. Иметь не более 7 дней).

Посмотрел команды DATE и DELIMS - не удалось найти решение.

Есть ли простое решение для создания имени файла, которое содержит день недели, то есть 0 в понедельник и т.д.

Или мне нужно прибегнуть к какой-то лучшей оболочке script.

Ответ 1

%DATE% не твой друг. Поскольку переменная среды %DATE% (и команда DATE) возвращает текущую дату с использованием формата короткой даты Windows, который полностью и бесконечно настраивается. Один пользователь может настроить систему на возврат 07/06/2012, в то время как другой может выбрать Fri060712. Использование %DATE% - полный кошмар для программиста BAT.

Существует два возможных подхода к решению этой проблемы:

  • Возможно, у вас возникнет соблазн временно изменить формат короткой даты, изменив настройки локали в значении реестра 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
    

    но этот метод имеет две проблемы:

    • он заносит глобальное значение реестра для своих локальных специфических purpouses, поэтому он может мешать другим процессам или задачам пользователя, которые в то же время запрашивают дату в формате коротких дат, в том числе и в случае запуска одновременно.

    • и он возвращает трехбуквенный день недели на локальном языке, который может отличаться в разных системах или разных пользователях.

  • используйте WMIC Win32_LocalTime, который возвращает дату удобным способом для непосредственного анализа с помощью команды FOR.

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

    это рекомендуемый мной метод.

Ответ 2

несколько способов:

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.Available по умолчанию во всех формах win7 и выше:

@echo off
setlocal
for /f %%d in ('"powershell (Get-Date).Day"') 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. Selfcompiled 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);

Ответ 3

@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 для понедельника и т.д.

Ответ 4

Я думал, что мой первый ответ дает правильный день недели как число от 0 до 6. Однако, поскольку вы не указали, почему этот ответ не дает желаемого результата, я могу только догадываться о причине.

Пакетный файл ниже создает файл журнала каждый день с цифрой в имени, 0 = воскресенье, 1 = понедельник и т.д. Программа предполагает, что echo %date% показывает дату в формате MM/DD/YYYY; если это не так, просто измените положение переменных mm и dd в команде for.

@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

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

Привет,

Антонио

Ответ 5

Это оказалось более сложным, чем я сначала подозревал, и я предполагаю, что то, что заинтриговало меня, я искал там, где и все приведенные методы не работали в Windows 7.

Итак, у меня есть альтернативное решение, которое использует Visual Basic Script.

Пакет создает и выполняет 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

EDIT:

Хотя я обратился к VBS, это можно сделать в чистой партии, потребовалось некоторое время, чтобы заставить его работать и много поискового LOL, но это, похоже, работает:

 @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

Ответ 6

Это работает для меня

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

Ответ 7

Это не моя работа (ну, я немного изменил ее в примере), и это поздно для игры, но для меня это работает на 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

Ответ 8

Сначала - скопировать 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% В ВАШЕМ SCRIPT

Ответ 9

Локально-зависимая версия: В некоторых средах следующее будет извлекать имя дня с даты:

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

Я в США. Я могу запустить этот код в 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.

Если сегодня четверг, он выведет "День Is: Thu".

Это возвращает день на все 4 версии Windows, в которые я тестировал. И только день. Когда я изменил настройку короткой даты на "ddd, M/d/yyyy", мой вывод отобразил бы день с запятой (например, Thu), которая говорит мне, что этот код использует короткий формат даты. Но то, что может также произойти, заключается в том, что если короткая дата не содержит дня недели, она может смотреть на формат длинных дат, который на всех четырех машинах, на которых я тестировал, имеет формат dddd в формате.

Ответ 11

У меня есть это решение для меня:

Создайте файл с именем dayOfWeek.vbs в том же каталоге, где будет выведен cmd файл.

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

Ответ 12

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

Если вы можете изменить формат короткой даты на ПК на "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

Ответ 14

Казалось, что нужно сделать это сам и увидеть жалобы на пустые строки:

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
)

Ответ 15

Версия с использованием 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