Установка переменной пакетного файла 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