为什么文件存在且文件大小检查无法组合使用?

问题描述 投票:1回答:1

我有一个我正在尝试编写的批处理文件的问题。

目标:检查logfile.log是否存在以及是否创建它。否则,如果文件已存在,则应检查文件大小。如果日志文件大小低于某个“无所事事”,则复制日志并使用新名称保存并重置实际日志文件的内容。

问题:由于某些原因,当我使用exist检查和size检查时,批处理不再工作了。

两个分开的操作都没有问题。如果我删除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%
)
batch-file logging filesize logfile
1个回答
2
投票

这个问题是由经典的delayed expansion陷阱引起的,每个初学者在批处理文件写入时都会在命令提示符窗口set /?中运行时从未读过命令SET输出的帮助。

在使用此命令块执行命令之前,Windows命令处理器会解析以(开头并以匹配的)结尾的命令块。在命令块解析期间,所有出现的%variable%都被引用的环境变量的当前值替换。这可以在debugging a batch file上看到。 请参阅How does the Windows Command Interpreter (CMD.EXE) parse scripts?

因此,在这种情况下,%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 /?

我建议还阅读:

© www.soinside.com 2019 - 2024. All rights reserved.