Почему файл существует, а проверки размера файла не работают в комбинации? - PullRequest
0 голосов
/ 03 марта 2019

У меня проблема с командным файлом, который я пытаюсь записать.

Цель: Проверить, существует ли logfile.log и не создавать ли его.В противном случае размер файла должен быть проверен, если файл уже существует.Если размер файла журнала ниже определенного значения «ничего не делать», скопируйте журнал и сохраните его под новым именем и сбросьте содержимое самого файла журнала.

Проблема: По какой-то причине пакет больше не работает, когда я использую exist check и size check.

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

set LOGFILE=%batdir%logfile.log
set maxbytesize=4000

if exist %LOGFILE% (
    for /F "usebackq" %%A IN ('%LOGFILE%') DO set size=%%~zA
    if %size% GTR %maxbytesize% (
        copy %LOGFILE% %LOGFILE%_%timestamp%
        :: overwrite existing file with ">"
        >%LOGFILE% echo Timestamp: %timestamplog%
        >>%LOGFILE% echo old log: %LOGFILE%_%timestamp%
    )
) else (
    echo Do Nothing >>%LOGFILE%
)

1 Ответ

0 голосов
/ 03 марта 2019

Эта проблема вызвана классическим отложенным расширением перехвата каждого новичка при записи командного файла, который никогда не читал справку команды SET при запуске в окне командной строки set /?.

Блок команд, начинающийся с ( и заканчивающийся соответствием ), анализируется командным процессором Windows до выполнения команды, использующей этот блок команд.Во время синтаксического анализа командного блока все вхождения %variable% заменяются текущими значениями указанных переменных среды.Это можно увидеть при отладке командного файла .
См. Также Как интерпретатор сценариев команд Windows (CMD.EXE) анализирует?

Итак, вэтот случай %size% заменяется ничем, поскольку эта переменная среды, скорее всего, не существует при выполнении командного файла до выполнения команды IF , которая проверяет наличие файла журнала.Определение переменной среды size внутри блока команд в реально существующем файле журнала не вступает в силу для %size%, уже замененного пустой строкой на этапе синтаксического анализа блока команд.

Наиболее вероятное лучшее решение в этомдело избегает всех командных блоков.Тогда отсроченное расширение переменной среды также не требуется.

@echo off
setlocal EnableExtensions DisableDelayedExpansion
set "LogFile=%~dpn0.log"
set "MaxLogFileSize=4000"

if not exist "%LogFile%" echo Do Nothing>>"%LogFile%"& goto DoMore

for %%I in ("%LogFile%") do set "LogFileSize=%%~zI"
if %LogFileSize% LSS %MaxLogFileSize% goto DoMore

for /F "tokens=2 delims==." %%I in ('%SystemRoot%\System32\wbem\wmic.exe OS GET LocalDateTime /VALUE') do set "TimeStamp=%%I"
set "FileTimeStamp=%TimeStamp:~0,4%-%TimeStamp:~4,2%-%TimeStamp:~6,2%_%TimeStamp:~8,2%-%TimeStamp:~10,2%-%TimeStamp:~12,2%"
set "TextTimeStamp=%TimeStamp:~0,4%-%TimeStamp:~4,2%-%TimeStamp:~6,2% %TimeStamp:~8,2%:%TimeStamp:~10,2%:%TimeStamp:~12,2%"

move /Y "%LogFile%" "%~dpn0_%FileTimeStamp%.log"
>"%LogFile%" echo Time stamp: %TextTimeStamp%
>>"%LogFile%" echo Old log: %~n0_%FileTimeStamp%.log

:DoMore
rem Add here more command lines using "%LogFile%".
endlocal

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

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

Пример:

@echo off
setlocal EnableExtensions DisableDelayedExpansion
set "LogFile=%~dpn0.log"
set "MaxLogFileSize=4000"
set "OldLogFile=%~dpn0_old.log"

if exist "%LogFile%" for %%I in ("%LogFile%") do if %%~zI GTR %MaxLogFileSize% move /Y "%LogFile%" "%OldLogFile%"

rem Add here more command lines using "%LogFile%".
endlocal

Пакетный файл перезаписывает файл *_old.log текущим файлом журнала с превышением лимита файла журнала.Таким образом, текущий файл журнала содержит зарегистрированную информацию о последних действиях, а файл *_old.log содержит архивную зарегистрированную информацию, записанную в течение определенного периода времени, в зависимости от того, сколько информации регистрируется при каждом выполнении пакетного файла и как часто выполняется пакетный файл.в течение определенного промежутка времени.Максимальное когда-либо необходимое место для хранения составляет примерно вдвое значение MaxLogFileSize, и никто больше не должен периодически удалять старые файлы журналов, которые никто больше не просматривал.

Примечание: Командный процессор Windows использует32-разрядная целочисленная арифметика со знаком.Таким образом, значение MaxLogFileSize должно быть на достаточное количество байт ниже максимального положительного 32-разрядного целого числа со знаком, равного 2 GiB или 2147483647 в байтах, чтобы предотвратить то, что текущий файл журнала станет больше или равен 2147483648 байтов.

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

  • call /? ... объясняет %~dpn0, который расширяется до диска, пути и имени пакетного файла без расширения файла.
  • echo /?
  • endlocal /?
  • for /?
  • goto /?
  • if /?
  • move /?
  • rem /?
  • set /?
  • setlocal /?
  • wmic /?
  • wmic os /?
  • wmic os get /?
  • wmic os get localdatetime /?

Я также рекомендую прочитать:

...