Bat сравнить дату создания файла с текущей датой

Обновлено: 04.07.2024

В пакетных файлах DOS способ достижения определенных целей несколько запутан. К счастью, существует отличный справочный сайт по пакетному сценарию: SS64 Саймона Шеппарда. (На том же сайте также есть много информации о Bash .)

Одна из трудностей - выполнение ветвления в зависимости от того, пуст ли каталог. Очевидное if exist "%dir%\*.*" не работает. Но это можно сделать с помощью этого трюка с условным выполнением:

Еще одна неудобная проблема - это разветвление по содержимому файла. Опять же, это можно сделать так:

Итак, мой вопрос:
Есть ли способ сделать ветвление в соответствии с отметками времени файлов?

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

К сожалению, это не совпадает с тем, что штампы даты совпадают. Поэтому нам просто нужно сначала проверить, имеют ли файлы одинаковую дату и время:

Ситуация Дэйва Уэбба, хотя и отличная, конечно же, будет работать только с файлами в том же каталоге.

Вот решение, которое будет работать с любыми двумя файлами.

Однако затем нужно вручную разбить дату и время на компоненты, поскольку Cmd.exe будет сравнивать их как укус, таким образом, 2> 10 и 10:00> 14:00.

Сравните сначала годы, затем месяцы, затем день, затем AM / PM, затем час, а затем минуту и ​​секунду (на самом деле это отнимает много времени, но у меня нет более точного представления о минуте), посмотрите окончательный код в конце.

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

Обратите внимание, что "ForFiles" имеет ограничение, заключающееся в том, что он не может использовать путь с пробелами, поэтому, если у вас есть путь с пробелами, вам сначала придется перейти в этот каталог, см. forfiles - пробелы в пути к папке

Код сравнения

Серьезно, вы должны начать изучать что-то еще. Это не шутка. DOS (cmd.exe) серьезно не хватает возможностей манипулирования датами и многих других недостатков. Вот следующая лучшая альтернатива, изначально предоставленная помимо пакета DOS, vbscript

Запустите его в командной строке

Конечно, в более новых версиях Windows вы можете попробовать Powershell .

Вот более простое решение. Объединив части даты как одну строку от наиболее значимой к наименее значимой, мы можем просто выполнить простое сравнение строк по результату.

Другими словами, сравнение значений YYYYMMDDAMPMHHMM даст желаемый результат без необходимости индивидуального сравнения каждого сегмента даты. Это значение получается путем объединения различных частей строки даты, извлеченных второй командой FOR.

Для одной конкретной ситуации, когда вы хотите сделать что-то в стиле Makefile, перезаписывая целевой файл на основе исходного файла, только если исходный файл новее, я придумал этот ужасный, но простой метод. Это вариант только в том случае, если вас никоим образом не заботит существующее содержимое файла назначения, которое старше исходного файла.

При этом xcopy перезаписывает файл назначения только в том случае, если исходный файл новее. Если он не новее, %% r равно «0 файлов скопировано», поэтому условная команда не выполняется, и целевой файл никогда не перезаписывается. Если он новее, %% r - это «1 файл (ы) скопирован», поэтому ваш целевой файл на короткое время является копией исходного файла, затем выполняется команда сборки, заменяющая ее новой версией того, что было в конечном файле. на самом деле должно быть.

Наверное, мне стоило просто написать скрипт на Perl.

(Примечание: вы также можете настроить xcopy для обработки ситуации, когда целевой файл изначально не существует, поставив звездочку в конце имени конечного файла; если вы этого не сделаете, то xcopy не уверен, является ли пункт назначения именем файла или именем папки, и нет флага для ответа по умолчанию для имени файла.)

Я бы использовал для этого xcopy:

Поскольку xcopy всегда возвращает true, в этом случае вам необходимо отфильтровать его вывод с помощью команды findstr.

  • / L предназначен только для перечисления, ничего не копируется.
  • / D выполняет сравнение времени. Подсказка: поменяв местами File1 и File2, вы можете решить, как обрабатывать идентичные файлы.
  • Параметр / Y необходим только для того, чтобы избежать вопроса «Перезаписать существующий».

Вот и все и работает с разными путями.

Вот краткое описание программы с веб-страницы:

На основе ответа Уэса я создал обновленный скрипт. Обновлений стало слишком много, чтобы комментировать их.











Эта тема родилась почти два года назад. Нам потребовалось самыми простыми средствами ТОЛЬКО командной строки получит временной слепок в формате ГГГГММДД_ччммсс (Год, Месяц, День, часы, минуты, секунды). В дальнейшем этот слепок предполагалось использовать в именах файлов для предотвращения путаницы в создаваемых однотипных файлах. Решение было найдено и использовалось некоторое время (решение опубликовано в виде статьи Подстановка текущих даты/времени в имя файла стандартными средствами командной строки Windows).
Впоследствии обнаружилась незавершенность алгоритма - ночное и утреннее время (промежуток между 00:00 и 10:00) в зависимости от региональных настроек может содержать ведущий пробел вместо нуля (" 9:59" вместо "09:59"). Для исправления этой ошибки была добавлена одна строка, и алгоритм заработал вновь.
Примерно через год возникла необходимость вернуться к этому алгоритму, и был найден более простой вариант решения проблемы - подстановки даты и времени в имя файла. Появилась заметка Дата и время в имени файла (подстановка стандартными средствами командной строки Windows). В заметке описывается суть нового алгоритма, использующего особенности метода раскрытия переменных и свойства конструкции for /f. Рассмотрим каждый из них в отдельности. В конце будет показан еще один пример использования этой методики.

Недостатки
Вначале хотелось бы сказать о существующих недостатках. Есть одна особенность, о которой следует помнить. Этот скрипт хорошо работает даже с таким форматом даты как М/Д/ГГГГ, например для даты 14 февраля 2010. Однако это никогда не проверялось, например, для дат неделей раньше. Об этом сказано в записи от 14 февраля 2009 на странице архива Роба ван дер Вуда. Однако в большинстве случаев это работает.

Раскрытие переменных
Конструкции вида %VAR:str1=str2% указывают интерпретатору раскрыть значение переменной VAR и произвести замену всех подстрок str1 на str2 во всей строке. Это хорошая особенность, которой мы можем воспользоваться - переменная %TIME% может содержать ненужный нам ведущий пробел и нам необходимо заменить его нулем

В данном случае str1 - это пробел, str2 - символ "ноль". Поэтому между двоеточием и знаком равенства один пробел. На всякий случай аналогичное проделываем и с переменной DATE.

Конструкция for /f
В зависимости от региональных настроек порядок элементов даты может варьироваться. Например, у нас принят формат ДД.ММ.ГГГГ, в некоторых англоговорящих странах ММ.ДД.ГГГГ. Для решения нашей проблемы надо выбрать каждую часть времени и отсортировать в нужном нам порядке - разбить строку на части по разделителям (точка ".", пробел " ", слеш "/", запятая ",", тире "-", двоеточие ":"), полученные части записать в переменные цикла и сохранить в нужном нам порядке

Рассмотрим, как же эта конструкция поможет нам. for /f рассматривает входной поток (текстовая строка. файл на диске или вывод команды). В данном случае это строка, например дата и время создания этой темы 21.01.2010 21:48:50,23 (согласно настроек на моей системе). Эта строка анализируется и разбивается разделителями на отдельные фрагменты (токены).
Обратите внимание на пробел в списке разделителей - "/-. ". Так как входная строка содержит только целочисленную информацию, разделенную разделителями, то в строке всего 7 токенов.
Для того чтобы все токены были переданы внутрь цикла указываем количество и список токенов - "tokens=1-7", то есть все семь - с первого по седьмой. Чтобы все семь токенов попали в цикл на обработку будут выделено семь переменных цикла. В заголовке цикла указано имя первой переменной %%a. Следующие переменные получат последовательно имена %%b, %%c, %%d, %%e, %%f, %%g. В первую переменную %%a попадет первый токен, во вторую, %%b - второй токен, и т.д.
И так. В этом примере порядок следующий (работает на моем компьютере, у вас может быть другой)
-- %%a - день
-- %%b - месяц
-- %%c - год
-- %%d - часы
-- %%e - минуты
-- %%f - секунды
-- %%g - сотые
Так как время 21.01.2010 21:48:50,23 из формата ДД.ММ.ГГГГ чч:мм:сс,сд надо перевести в формат ГГГГММДД_ччмм, надо взять значения переменных из списка выше в следующем порядке
-- %%c - год
-- %%b - месяц
-- %%a - день
-- %%d - часы
-- %%e - минуты

В результате получим строку вида 20100121_2148.

Этот скрипт не универсальный, он системно-зависимый: порядок отдельных частей даты и времени зависит от текущих установок на компьютере (национальные, пользовательские настройки).

Aнализ текущего времени
На форуме был задан вопрос как проанализировать текущее время:

. нужно в процессе выполнения скрипта проанализировать текущее время, если текущее время меньше 15:00 , то пропускаем (по goto) определённую строку (блок).

Используем раскрытие переменных с заменой подстроки - берем значение переменной TIME, производим замену пробела нулем и полученную строку сравниваем с заданной строкой времени. Так как сравнение производится лексикографически (википедия), то алгоритм выполнится корректно

Изначально я думал, что моя проблема очень проста - запишите дату изменения txt-файла, расположенного в указанном каталоге, сравните эту дату с текущей датой и, если они совпадают, сделайте что-нибудь. Если нет, тогда делайте что-нибудь еще.

Строка, которую я использую для захвата текущей даты:

Строки, которые я использую, чтобы зафиксировать дату изменения моего указанного файла:

В приведенном выше случае я просто использую echo , чтобы увидеть, что возвращается, и кажется, что дата возвращается, но я получить дополнительную информацию:

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

3 ответа

Мне нравится способ dbenham , но если вы хотите, чтобы ваш код работал, вы можете сделать это следующим образом:

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

Работать с датами в пакете намного сложнее, чем должно быть.

В этом случае есть одна команда, которая может облегчить вашу работу. FORFILES имеет возможность обрабатывать файлы, которые были изменены с определенной даты. Используйте FORFILES /? из командной строки, чтобы получить документацию по его использованию.

Эта простая команда выведет список всех файлов, которые были изменены сегодня:

Если найден хотя бы один файл, для параметра ERRORLEVEL установлено значение 0, в противном случае для параметра ERRORLEVEL установлено значение 1.

У вас есть определенный файл, поэтому вы можете использовать

Существует более краткий способ сделать это. Оператор && используется для условного выполнения команд, если предыдущая команда была успешной, || используется для условного выполнения команд, если предыдущая команда не выполнена. Однако будьте осторожны, команды || также будут выполняться, если && команда (ы) не выполнена.

Помимо вопросов, поднятых в комментариях, прилагаемых к статье TechNet, в которой описаны документы ForFiles Документация ForFiles в Microsoft TechNet , есть еще одна проблема, о которой упоминается, но только если вы читаете между строками о том, что часовой пояс игнорируется. Поскольку ForFiles оценивает дату изменения, указанную по местному времени, он будет рассматривать файл, измененный в 02:01 EST , как более старый , чем файл, измененный в 02:59 EDT. .

Пакетные файлы *.bat (*.cmd) — Как создать папку с именем равным текущей дате?

Такая команда создаст в корне системного диска папку с именем равным текущей дате. Эта команда не сработает, если региональные установки отличны от русского и в разделителях даты используется слеш. В таком случае, поможет один из следующих скриптов:

md %systemdrive%\%date:

md %systemdrive%\%date:

Во втором случае, папки будут сортироваться по алфавиту.

Как вариант, можно рассмотреть добавление к имени файла текущей даты:

@echo off
for /F "tokens=1-4 usebackq delims=. " %%1 in (`date /t`) do set mydate=%%4.%%3.%%2
ren test.txt test%mydate%.txt

Имя файла test.txt будет переименовано в test2005.03.05.txt.

Как запретить повторный запуск приложения.
Если приложение запускается bat-файлом, то отследить (и запретить) его повторный запуск можно таким образом:

pslist.exe -e "процесс"
if %errorlevel%==1 start "" "программа"

pslist - бесплатная утилита, которую можно скачать здесь.
-е для поиска точного имени процесса, иначе находит любые процессы с подходящим началом имени.

Автоматическое создание резервной копии данных.
Скрипт архивирует папку файлопомойки (\\SERVER\e$\Exchange)
и папку с данными юзеров (домашнюю Данные пользователей (\\SERVER\e$\Departments))
Скрипт не архивирует медиафайлы, так как они занимают вагон места и их потеря у меня не критична

rem *******************
rem задаём винты где лежат папки для архивирования и винт куда будем бэкапить
rem *******************
SET DRIVE1ST=d:
SET DRIVE2ND=e:

rem *******************
rem пароль на архив
rem *******************
SET PASSWD=qmsdhgsdfgsdfhdsfhsdhf

rem *******************
rem если копировать для надёжности куданить на сетку
rem *******************
rem SET COPYTO=\\shpakk\c$\!backup

rem ********************
rem *** Проверим путь назначения архива
rem ********************
%DRIVE1ST%
if not exist \!backup md \!backup
if not exist \!backup\Departments md \!backup\Departments
if not exist \!backup\Exchange md \!backup\Exchange
if not exist \!backup\MEDEA_rdisk md \!backup\MEDEA_rdisk
cd \!backup

rem ******************************
rem *** Backup \\SERVER\e$\Exchange
rem ******************************
SET DIRNAME=Exchange
SET FILENAME=SERVER_Exchange
SET SOURCEDIR=e:\Exchange
rar a -r -m5 -dh -x*.mp3 -x*.fcd -x*.avi -x*.zip -x*.rar -x*.exe -w%DRIVE2ND%\ -p%PASSWD% %DIRNAME%\%FILENAME%_new %SOURCEDIR%\*.*
if not exist %DIRNAME%\%FILENAME%_new.rar goto next2
del %DIRNAME%\%FILENAME%_old.rar
ren %DIRNAME%\%FILENAME%.rar %FILENAME%_old.rar
ren %DIRNAME%\%FILENAME%_new.rar %FILENAME%.rar
copy %DIRNAME%\%FILENAME%.rar %COPYTO%\%DIRNAME%

:next2
rem ***************************
rem *** Backup \\SERVER\e$\Users
rem ***************************
SET DIRNAME=Departments
SET FILENAME=SERVER_Departments
SET SOURCEDIR=e:\Departments
if not exist %DIRNAME%\%FILENAME%_new.rar goto next3
del %DIRNAME%\%FILENAME%_old.rar
ren %DIRNAME%\%FILENAME%_4.rar %FILENAME%_old.rar
ren %DIRNAME%\%FILENAME%_3.rar %FILENAME%_4.rar
ren %DIRNAME%\%FILENAME%_2.rar %FILENAME%_3.rar
ren %DIRNAME%\%FILENAME%_new.rar %FILENAME%_2.rar
:next3
rem *******************
rem это если архив будет большим - кусками бить -v357888k
rem *******************
rem rar a -r -m5 -v357888k -dh -x*.mp3 -x*.fcd -x*.avi -x*.exe -w%DRIVE2ND%\ -p%PASSWD% %DIRNAME%\%FILENAME%_new %SOURCEDIR%
rem *******************
rem архивирование пошло, не берём мультимедиа файлы
rem *******************
rar a -r -dh -x*.mp3 -x*.fcd -x*.avi -x*.exe -x*.jpg -x*.tif -p%PASSWD% %DIRNAME%\%FILENAME%_new %SOURCEDIR%
goto next4

:next4
rem **********************************
rem *** Create repair disk on \\SERVER
rem **********************************
SET DIRNAME=MEDEA_rdisk
SET FILENAME=MEDEA_rdisk
SET SOURCEDIR=%windir%\repair
%windir%\system32\rdisk.exe /s-
rar a -r -m5 -dh -w%DRIVE2ND%\ -p%PASSWD% %DIRNAME%\%FILENAME%_new %SOURCEDIR%\*.*
if not exist %DIRNAME%\%FILENAME%_new.rar goto next5
del %DIRNAME%\%FILENAME%_old.rar
ren %DIRNAME%\%FILENAME%.rar %FILENAME%_old.rar
ren %DIRNAME%\%FILENAME%_new.rar %FILENAME%.rar
copy %DIRNAME%\%FILENAME%.rar %COPYTO%\%DIRNAME%

В итоге имеем 3 папки:

Departments, в ней:
SERVER_Departments_2.rar - 2х дневной давности
SERVER_Departments_3.rar - 3х дневной давности
SERVER_Departments_4.rar - 4х дневной давности
SERVER_Departments_new.rar - НОВЫЙ
SERVER_Departments_old.rar - СТАРЫЙ

Exchange
Так как архивируем обменник - он нам сильно то и не нужен храним только сегодняшний и вчерашний архивы
SERVER_Exchange.rar
SERVER_Exchange_old.rar

ну и систему на всякий в папке
SERVER_rdisk
SERVER_rdisk.rar
SERVER_rdisk_old.rar

Как добавить комментарии в bat-файл.
При написании большого пакетного файла очень полезно добавлять комментарии к его основным блокам. Это позволит с легкостью разобраться в том, что делают эти блоки по прошествии времени.
Комментарии можно добавить несколькими способами. Первый больше годится для написания больших комментариев, описывающих либо весь пакетный файл, либо несколько больших его блоков. Код выглядит следующим образом:

goto start
--------------------------------------
Этот пакетный файл предназначен
для автоматизации рутинных операций,
выполняемых ночью для синхронизации
содержимого корпоративного ftp-сервера
с ftp-серверами филиалов
--------------------------------------
Пакетный файл написан 01/01/2004
Последнее исправление внесено 10/02/2004
--------------------------------------
И т.д.
:start

Такое написание комментария при запуске пакетного файла передаст управление сразу к команде, следующей за меткой start. За это отвечает оператор перехода goto.
Более простые комментарии можно добавить, начиная строки с команды rem или с двух двоеточий, идущих друг за другом.

rem Этот блок устанавливает соединение с удаленным сервером

:: Этот блок проверяет дату изменения файлов

Комментирование больших пакетных файлов (как, в принципе, и любого кода) - хороший тон, который значительно облегчает процесс разбора этих файлов другими людьми или самим автором по прошествии значительного времени с момента написания.

Как в bat файле дождаться появления определенного файла.
Иногда необходимо при появлении определенного файла в папке выполнить какое-то действие. Чтобы организовать проверку появления файла в папке можно использовать следующий пакетный файл

:test
if exist c:\1.txt goto go
sleep 10
goto test
:go
notepad

Такой пакетный файл будет проверять с интервалом 10 секунд наличие в корне диска С файла 1.txt и когда файл 1.txt появится, будет выполнено действие, указанное после метки go, т.е. в этом примере будет запущен Блокнот.
Утилита sleep свободно распространяется в составе Resource Kit. Вы можете её скачать здесь.
Если файл 1.txt большого размера и копируется откуда-то, то может получится так, что пакетный файл проверит его наличие в то время, как файл еще не скопировался или занят другим приложением. В таком случае, попытка выполнить какие-то действия с файлом 1.txt приведет к ошибке. Чтобы этого не произошло пакетный файл можно модифицировать следующим образом

:test
if exist c:\1.txt goto go
sleep 10
goto test
:go
rename c:\1.txt 1.txt
if not errorlevel 0 goto go
del c:\1.txt

Когда файл 1.txt скопировался на диск С не полностью, либо занят другим приложением, попытка его переименовать вызовет ошибку и цикл будет повторяться до тех пор, пока файл не скопируется полностью либо не будет освобожден. После того, как команда rename c:\1.txt 1.txt будет выполнена без ошибки (т.е. файл свободен), то с ним можно выполнять любые действия. В последнем примере это его удаление.

Как из bat файла обойти проверку даты.
Некоторое программное обеспечение при запуске проверяет текущую системную дату. Если дата больше, чем заложено разработчиком, то программа не запускается. Например, разработчик считает, что версия программы может отработать месяц, а потом пользователь должен будет установить обновленную версию программы. С одной стороны это забота о пользователе, который будет иметь в своем распоряжении свежую версию программы с устраненными недочетами, по отношению к прошлым версиям. С другой стороны, производитель вынуждает пользователя скачивать новую версию даже если пользователя полностью устраивает та версия программы, которая у него установлена. Данную проблему можно легко решить при помощи следующего пакетного файла, который будет запускать программу, дожидаться ее завершения и возвращать дату на ту, которая была до запуска программы.

set tempdate=%date:

-10%
date 01-01-04
notepad.exe
date %tempdate%

set tempdate=%date:

-10%
date 01-01-04
start notepad.exe
date %tempdate%

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

Читайте также: