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

<p>у меня есть пакетный файл windows, который запускается ежедневно. желаете записать данные в файл и хотите повернуть его (т.е. иметь данные не более, чем за последние 7 дней).</p><p>посмотрел команды <code>date</code> и <code>delims</code> - не могу найти решение.</p><p>есть ли простое решение для создания имени файла, который содержит день недели, т.е. 0 для понедельника и т.д.</p><p>или я должен прибегнуть к какому-нибудь лучшему сценарию shell.</p>

<p><code>%date%</code> не твой друг. потому что переменная среды <code>%date%</code> (и команда <code>date</code>) возвращает текущую дату, используя windows <em>краткий формат даты</em>, который полностью и бесконечно настраивается. один пользователь может настроить систему на возвращение 07/06/2012, а другой может выбрать fri060712. использование <code>%date%</code> - полный кошмар для программиста на bat. </p><p>есть два возможных подхода к решению этой проблемы:</p><ol> <li><p>возможно, у вас возникнет соблазн временно изменить формат короткой даты, изменив настройки локали в значении реестра <code>hkcu\control panel\international\sshortdate</code> на ваш распознаваемый формат. затем получите доступ к <code>%date%</code>, чтобы получить дату в нужном формате; и, наконец, восстановить формат обратно в исходный пользовательский формат. что-то вроде этого</p> <pre><code>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 </code></pre> <p>но у этого метода есть две проблемы: </p> <ul> <li><p>он вмешивается в значение глобального реестра для своих локальных конкретных целей, поэтому он может мешать другим процессам или пользовательским задачам, которые в то же время запрашивают дату в коротком формате даты, в том числе и себя, если они выполняются одновременно. </p></li> <li><p>и он возвращает трехбуквенный день недели на местном языке, который может отличаться в разных системах или у разных пользователей.</p></li> </ul></li> <li><p>используйте<strong> wmic win32\_localtime </strong>, который возвращает дату удобным способом, чтобы непосредственно проанализировать ее с помощью команды <code>for</code>.</p> <pre><code>for /f "skip=1" %%a in ('wmic path win32\_localtime get dayofweek' ) do ( set dow=%%a ) </code></pre> <p>это метод, который я рекомендую.</p></li> </ol>

<pre><code>@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 </code></pre><p>dow - 0 для воскресенья, 1 для понедельника и т.д.</p>

<p>я думал, что мой первый ответ дает правильный день недели в виде числа от 0 до 6. однако, поскольку вы <em>not</em> указали, почему этот ответ не дает желаемого результата, я могу только догадываться о причине.</p><p>пакетный файл ниже создает файл журнала каждый день с цифрой в имени, 0 = воскресенье, 1 = понедельник и т.д. ... программа предполагает, что <code>echo %date%</code> показывает дату в формате mm/dd/yyyy; если это не так, просто измените положение переменных mm и dd в команде <code>for</code>.</p><pre><code>@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 </code></pre><p>если это не то, что вы хотите, пожалуйста, укажите проблему, чтобы я мог ее исправить.</p><p><strong>edit</strong>: версия ниже получает части даты независимо от настроек локали:</p><pre><code>@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 </code></pre><p><strong>edit</strong>: в приведенной ниже версии укажите день недели как трехбуквенное короткое имя:</p><pre><code>@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 </code></pre><p>с уважением,</p><p>антонио</p>

<p>первый - копировать con setupday.001 set workday = ^ z (очень важно - нет cr/lf)</p><pre><code>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% </code></pre><p>используйте% weekday% в вашем скрипте</p>

<p>это не моя работа (ну, я немного изменил ее из примера), и уже поздно для игры, но это работает на server 2003 для меня;</p><pre><code>@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 </code></pre><p>цитирование: <a href="http://www.techsupportforum.com/forums/f128/solved-windows-7-batch-getting-day-of-week-moved-from-vista-7-a-565632.html#post3217395">techsupportforum</a> </p>

<p>это работает для меня </p><pre><code>for /f "tokens=3" %%a in ('robocopy ^|find "started"') do set today=%%a </code></pre>

<p>это оказалось намного сложнее, чем я сначала подозревал, и я думаю, это то, что заинтриговало меня, я искал везде, где и все методы, приведенные не будут работать на windows 7.</p><p>таким образом, у меня есть альтернативное решение, которое использует скрипт visual basic. </p><p>пакет создает и выполняет сценарий (dayofweek.vbs), назначает вывод сценариев (понедельник, вторник и т.д.) переменной (dow), затем проверяется переменная, а другая переменная (dpwnum) присваивается с номером дня, после чего vbs удаляется надеюсь, это поможет:</p><pre><code>@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 </code></pre><p>правка:</p><p>хотя я обратился к vbs, это может быть сделано в чистом виде, мне потребовалось некоторое время, чтобы заставить его работать и много искать lol, но это, кажется, работает:</p><pre><code> @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 </code></pre><p>единственное предостережение для вас в вышеупомянутой партии: день недели от 1 до 7, а не от 0 до 6.</p>

<p>у меня есть это решение работает на меня:</p><p>создайте файл с именем dayofweek.vbs в том же каталоге, куда будет помещен cmd-файл.</p><p><strong> dayofweek.vbs </strong>содержит одну строку:</p><pre><code>wscript.stdout.write weekdayname(weekday(date)) </code></pre><p>или, если вы хотите номер дня вместо имени:</p><pre><code>wscript.stdout.write weekday(date) </code></pre><p>файл cmd будет иметь следующую строку:</p><pre><code>for /f %%a in ('cscript dayofweek.vbs //nologo') do set dayname=%%a </code></pre><p>теперь вы можете использовать переменную<strong> dayname </strong>like:</p><pre><code>robocopy c:\inetpub \\dcstorage1\share1\webserver\inetpub\_%dayname% /s /xd history logs </code></pre>

<p>я в сша. я могу запустить этот код в windows 7, windows 2008 r2, windows server 2003, windows xp (все операционные системы имеют обновления и исправления windows). все с короткой настройкой даты без ddd (или dddd) (день недели).</p><pre><code>@echo off for /f %%a in ('date /t') do set day=%%a echo. echo the day is: %day% echo. </code></pre><p>если сегодня четверг, будет выведено «день: чт».</p><p>это возвращает день на всех 4 версиях windows, на которых я тестировал. и только день. когда я изменил настройку своей короткой даты на «ddd, m/d/yyyy», мои выходные данные будут показывать день с запятой (например, чт,), которая говорит мне, что этот код использует формат короткой даты. но может также случиться так, что если короткая дата не содержит дня недели, она может посмотреть на формат длинной даты, который на всех 4 машинах, на которых я тестировал, имеет dddd в формате.</p>

<p><strong> зависимая от локали версия: </strong>в некоторых средах следующее извлекает название дня из даты:</p><pre><code>set dayname=%date:~0,3% </code></pre><p>предполагается, что имя дня является первой частью <code>%date%</code>. однако в зависимости от настроек машины часть подстроки (<code>~0,3</code>) должна будет измениться.</p><p>такая инструкция выдает дамп в файл с трехзначным именем дня:</p><pre><code>set logfile=%date:~0,3%.log echo some stuff > %logfile% </code></pre><p><strong> независимая от локали версия: </strong>если вам нужно меньше зависеть от формата дня текущей машины, другой способ сделать это - написать крошечное приложение, которое печатает день недели. затем используйте вывод этой программы из командного файла. например, следующее приложение c печатает <code>dayn</code>, где n = 0..6.</p><pre><code>#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 ); } </code></pre><p>если вышеупомянутое было скомпилировано и связано как <code>myday.exe</code>, то вы можете использовать его из командного файла, например так:</p><pre><code>for /f %%d in ('myday.exe') do set logfile=%%d.log echo some stuff > %logfile% </code></pre>

<p>если вы можете изменить формат короткой даты на пк на «ddd yyyy-mm-dd» (обязателен только первый параметр «ddd»), то следующая команда вернет:</p><pre><code>c:\>vol | date the current date is: mon 2014-12-01 </code></pre><p>затем вы можете написать свой пакетный файл -</p><pre><code>@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 </code></pre>

<p>искал это сделать сам и видел жалобы на пустые строки:</p><pre><code>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 ) </code></pre>

<pre><code>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 </code></pre>

<p>еще одно вращение на эту тему. приведенный ниже скрипт отображает несколько дней вокруг текущего с префиксом дня недели.</p><p>в основе лежит отдельная процедура: dpack, которая кодирует дату в значение, по модулю 7 которого отображается день недели в соответствии со стандартами iso 8601 (mon == 0). также предоставляется: dunpk, которая является обратной функцией:</p><pre><code>@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 </code></pre>

<p>я улучшил aacini <a href="https://stackoverflow.com/a/11493557/8604593">ответ</a> , чтобы сделать его echo полный день недели имя </p><p>так вот мой код</p><pre><code>@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 </code></pre>