it-swarm.com.ru

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

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

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

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

Или я должен прибегнуть к какому-нибудь лучшему сценарию Shell.

18
Ed Heal

%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
    )
    

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

27
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 .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);
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; если это не так, просто измените положение переменных 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

Если это не то, что вы хотите, пожалуйста, укажите проблему, чтобы я мог ее исправить.

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: В приведенной ниже версии укажите день недели как трехбуквенное короткое имя:

@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

Это оказалось намного сложнее, чем я сначала подозревал, и я думаю, это то, что заинтриговало меня, я искал везде, где и все методы, приведенные не будут работать на 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, это может быть сделано в чистом виде, мне потребовалось некоторое время, чтобы заставить его работать и много искать 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.

2
David Kroukamp

У меня есть это решение работает на меня:

Создайте файл с именем 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 like:

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 (все операционные системы имеют обновления и исправления Windows). Все с короткой настройкой даты без DDD (или DDDD) (день недели).

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

Если сегодня четверг, будет выведено «День: Чт».

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

1
user2316634

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

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%
1
Mark Wilkins

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

Еще одно вращение на эту тему. Приведенный ниже скрипт отображает несколько дней вокруг текущего с префиксом дня недели.

В основе лежит отдельная процедура: dpack, которая кодирует дату в значение, по модулю 7 которого отображается день недели в соответствии со стандартами ISO 8601 (Mon == 0). Также предоставляется: 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 Ответ , Чтобы сделать его 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