Работа с датой, временем. Примеры bat / cmd файлов.
Хотел бы обратить ваше внимание на то, что если в номере месяца, дня или данных времени присутствует ведущий ноль - он должен быть удален перед выполнением арифметических действий. Это делается потому, что в bat файлах числа (не строки!), начинающиеся с 0, считаются восьмеричными. Следовательно такие числа, как 08 и 09 не имеют смысла, так как цифр 8 и 9 нет в восьмеричной системе счисления.Не забывайте об этом при арифметической обработке данных!
Вместо проверки и удаления ведущих нулей, учитывая, что эти числа меньше ста, можно использовать следующий прием:
set /a m=100%dd%%%100
Итак, рассмотрим некоторые примеры решения задач, связанных с обработкой даты и/или времени.
Определения названия дня недели по номеру дня в неделе.
:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
:Day2Name %d% day
:: By: Ritchie Lawrence, 2002-10-04. Version 1.0
:: Func: Returns the day of week from the day number, 1=Monday, 7=Sunday.
:: For NT4/2000/XP/2003.
:: Args: %1 day number to convert to name of day of week, 1 to 7 (by val)
:: %2 var to receive name of day of week (by ref)
:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
for /f "tokens=%1" %%a :
in ('echo Понедельник Вторник Среда Четверг Пятница Суббота Воскресение') ^
do set %2=%%a
exit /b 0
Пример вызова
call :Day2Name 2 day
echo Второй день недели - это %day%
Еще один вариант решения этой задачи:
:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
:Day2Name %d% day
set map=1-Понедельник;2-Вторник;3-Среда;4-Четверг;^
5-Пятница;6-Суббота;7-Воскресение;
CALL SET v=%%map:*%1-=%%
SET v=%v:;=&rem.%
set %2=%v%
exit /b 0
Пример вызова аналогичен предыдущему.
Написать процедуру получения имени месяца по его номеру, думаю, уже не составит труда.
-------------------------------------------------------------------------------------------------------
Удаление файлов с истекшим временем хранения
В следующем примере из заданной папки (OTKUDA) по требуемой маске (MASK) удаляются файлы, которые были созданы более определенного количества дней назад (N).
@echo off
setlocal enabledelayedexpansion
rem age files in days
set N=14
set MASK=*.bak
set OTKUDA=D:\00tt\00
call :raschet %date% days_to_today
pushd %OTKUDA%
for /f "tokens=*" %%a in ('dir /b /a:-d %MASK%') do (
set filedate=%%~ta
call :raschet !filedate:~0,10! days_to_date_of_file
set /a raznitsa=%days_to_today%-!days_to_date_of_file!
if !raznitsa! gtr %N% del /q "%%a"
)
popd
exit
:raschet
for /f "delims=. tokens=1-3" %%a in ('echo %~1') do (
set /a years=%%c*365+%%c/4
set /a prev_year=%%c-1
set /a result_year=%%c/4
set /a result_prev_year=!prev_year!/4
set /a vis=!result_year!-!result_prev_year!
if !vis!==1 (
if %%b==01 set /a years=!years!-1
if %%b==02 set /a years=!years!-1
)
if %%b==01 set months=0
if %%b==02 set months=31
if %%b==03 set months=59
if %%b==04 set months=90
if %%b==05 set months=120
if %%b==06 set months=151
if %%b==07 set months=181
if %%b==08 set months=212
if %%b==09 set months=243
if %%b==10 set months=273
if %%b==11 set months=304
if %%b==12 set months=334
set days=%%a
set firstsym=!days:~0,1!
if !firstsym!==0 set days=!days:~1,1!
set /a %~2=!years!+!months!+!days!
)
Приведенный выше пример, который не содержит и 50 строк кода, показывает, что несмотря на то, что средства командного языка очень ограничены, его возможности позволяют писать не только самые простые сценарии.
Но целесообразность использования именного этого средства для конкретной задачи определять вам.
Посмотрел внимательно предыдущий пример и переделал его.
Теперь он не занимает и 40 строк. И, безусловно, его еще можно сократить! Если поставить именно такую цель. В данном же случае цель примеров - показать возможности и различные приемы написания bat файлов. По той же причине предыдущий пример пока не удалил, так как, на мой взгляд, он легче для понимания.
@echo off
setlocal enabledelayedexpansion
set N=14
set MASK=*.php
set OTKUDA=D:\00tt\00
call :raschet %date% days_to_today
pushd %OTKUDA%
for /f "tokens=*" %%a in ('dir /b /a:-d %MASK%') do (
set filedate=%%~ta
call :raschet !filedate:~0,10! days_to_date_of_file
set /a raznitsa=%days_to_today%-!days_to_date_of_file!
if !raznitsa! gtr %N% del /q "%%a"
)
popd
exit
:raschet
for /f "delims=. tokens=1-3" %%a in ('echo %~1') do (
set /a years=%%c*365+%%c/4
set /a prev_year=%%c-1
set /a result_year=%%c/4
set /a result_prev_year=!prev_year!/4
set /a vis=!result_year!-!result_prev_year!
set numm=%%b
if "!numm:~0,1!" == "0" set numm=!numm:~1,1!
if !vis!==1 (
if !numm! LSS 3 set /a years=!years!-1
)
call :Day2Num !numm! months
set days=%%a
if "!days:~0,1!" == "0" set days=!days:~1,1!
set /a %~2=!years!+!months!+!days!
)
exit /b 0
:Day2Num %d% day
for /f "tokens=%1" %%I in ^
('echo 0 31 59 90 120 151 181 212 243 273 304 334') ^
do set /a %2=%%I
exit /b 0
В этом примере подпрограмма Day2Num в некоторой степени имитирует работу с массивом констант.))
Если же рассматривать практическую сторону задачи - удаление файлов старше определенного количества дней - то нельзя не упомянуть еще несколько способов решения задачи.
Утилита robocopy позволяет (среди прочего) перемещать файлы по условию, например, старше определенного количества дней. Непосредственно удалять эта утилита не позволяет, поэтому файлы по условию перемещаются во временную директорию, а уже оттуда отправляются на Небесный Независающий Сервер (командой del).
...
set robotemp=%TEMP%\robotemp
MD %robotemp%
ROBOCOPY "C:\source_folder" %robotemp% /move /minage:7
del %robotemp% /q
...
В приведенном участке кода из папки C:\source_folder удаляются файлы, возраст которых больше 7 дней.
В том же пакете Resource Kit, а начиная с Windows VISTA - как стандартный компонент, есть и более приспособленная для этого утилита - forfiles.
Надо заметить, что параметры этой программы... как бы так сказать... несколько нестандартные. Но ряд преимуществ, которые она дает, стоят того, чтобы в них разобраться. Для решения нашей задачи используется следующий вызов:
forfiles /p "C:\source_folder" /s /m *.* /c "cmd /c Del @path /q" /d -7
Подробнее о параметрах forfiles смотрите тут.
-------------------------------------------------------------------------------------------------------
Для вопросов, обсуждений, замечаний, предложений и т. п. можете использовать раздел форума этого сайта (требуется регистрация).
Новый раздел о средствах командной строки в рамках этого же проекта расположен здесь