【问题标题】:Batch Function can't write to log variable批处理函数无法写入日志变量
【发布时间】:2023-04-07 03:02:01
【问题描述】:

我有一个批处理脚本,它进入文件夹的子文件夹(不包括一个文件夹)获取 .log 文件,将它们归档,然后删除原始文件。

文件夹结构:

\Logs\logs1
\Logs\logs2
\Logs\logs3

最初,我只将这个循环作为一行,它的工作原理如下:

FOR /F "usebackq tokens=* delims=" %%A IN (`DIR "%LogsFilespec%" /B /S ^|find ^"logs3^" /v `)  DO %zipCommand% >> %ProcessLog% & DEL "%%~fA" & ECHO Deleting "%%~fA"  >> %ProcessLog% & ECHO. >> %ProcessLog%

但是,我被指示将它变成一个看起来更简单的 FOR DO CALL,结果我被卡住了,不确定出了什么问题。 %targetDate% 是 YYYYMMDD。

**根据 rojo 的建议编辑了更完整的代码:

SET ProcessLog=C:\Users\Me\Documents\batch_files\%~n0_%jobLog%.txt

:DetermineArchiveApp
:: Create specifics for ITD Logs collection
SET ITDLogsLocation=C:\Users\Me\Documents\fakeG
SET ITDLogsName=trace*%targetDate%.log
SET ITDLogsFilespec=%ITDLogsLocation%\%ITDLogsName%

:: ********************************************************************************
:: * Check if server has WinZip or 7-Zip installed. setup environment variable    *
:: * accordingly with executable path and name, and with any required parameters. *
:: ********************************************************************************

SET PathWinZip="C:\Program Files\WinZip\wzzip.exe"
SET Path7Zip_64bit="C:\Program Files\7-Zip\7z.exe"
SET Path7Zip_32bit="C:\Program Files (x86)\7-Zip\7z.exe"
SET Path7Zip_true="C:\Users\Me\Documents\batch_files\7za.exe"

:: Check for 32-bit version of 7-Zip. If found, configure
:: its command line parameter to produce a .zip file
IF EXIST %Path7Zip_32bit% SET zipCommand=%Path7Zip_32bit% a

::Check for WinZip
IF EXIST %PathWinZip% SET zipCommand=%PathWinZip% -a

:: Check for 64-bit version of 7-Zip. If found, configure
:: its command line parameter to produce a .zip file
IF EXIST %Path7Zip_64bit% SET zipCommand=%Path7Zip_64bit% a

:: Check for 64-bit version of 7-Zip. If found, configure
:: its command line parameter to produce a .zip file
IF EXIST %Path7Zip_true% SET zipCommand=%Path7Zip_true% a


:ArchiveProcess
ECHO ***************************************************** >> %ProcessLog%
::Write the date and time of job starting to a log
ECHO %DATE% %TIME% START >> %ProcessLog%
::Loop through the list that DIR gives for the given folder, and for each folder do zipCommand, excluding ITD\Data\AFS, and write to log
FOR /F "delims=" %%A IN (
    'DIR "%LogsFilespec%" /B /S ^|find /v "logs3"'
) DO CALL :DoZip "%%~dpnA" "%%~fA" "%zipCommand%" "%ProcessLog%"
::Write end to log
ECHO %DATE% %TIME% %~nx0 END >> %ProcessLog%
ECHO ***************************************************** >> %ProcessLog%

:DoZip
setlocal
SET "archiveName=%~1"
SET "SourceFileSpec=%~2"
SET "zipCommand=%~3"
SET "RunLog=%~4"

>>"%RunLog%" (

    echo Archiving %SourceFileSpec%...
    "%zipCommand%" "%archiveName%.zip" "%SourceFileSpec%"

    echo %TIME% Deleting %SourceFileSpec%...
    DEL "%SourceFileSpec%"

    echo;
)
GOTO :EOF

我从 cmd NOW 得到的错误是:

'""' 不是内部或外部命令、可运行程序或批处理文件。

两者的语法有什么问题!?

编辑 2:现在回家,还不能远程工作,所以我明天会回来。 当前的问题是:7zip命令行不喜欢

"C:\Users\Me\Documents\batch_files\7za.exe" a

而且 >>"%RunLog%" 块也不起作用,如果只注释掉存档和删除行以查看发生了什么,我就会被抛出

The system cannot find the drive specified.
The system cannot find the drive specified.
The system cannot find the drive specified.
The system cannot find the drive specified.
The system cannot find the path specified.

【问题讨论】:

标签: batch-file for-loop logging 7zip


【解决方案1】:

我看到的最大区别是,在你成功的单行词中,你有正确引用的东西;而在调用者和子例程中的call 中,您什么都不引用。如果您的任何路径包含空格或特殊字符,就会发生灾难。试试这个:

FOR /F "delims=" %%A IN (
    'DIR "%LogsFilespec%" /B /S ^|find /v "logs3"'
) DO CALL :DoZip "%%~dpnA" "%%~fA" "%zipCommand%" "%ProcessLog%"

...

:DoZip <basename> <fqpath> <zipcmd> <log>
setlocal
SET "archiveName=%~1"
SET "SourceFileSpec=%~2"
SET "zipCommand=%~3"
SET "RunLog=%~4"

>>"%RunLog%" (

    echo Archiving %SourceFileSpec%...
    "%zipCommand%" "%archiveName%.zip" "%SourceFileSpec%"

    echo %TIME% Deleting %SourceFileSpec%...
    DEL "%SourceFileSpec%"

    echo;
)
GOTO :EOF

顺便问一下,你知道你可以zip without 3rd party software吗?


这整个磨难正在变成一团糟。我希望您能允许我提供一些一般性的脚本建议,并将其视为善意而不是批评。

当您在批处理脚本中将变量设置为字符串时,它有助于 set "var=value" 引用 var=value 对。当您需要在引号内评估您的变量时,将其称为"%var%"。这消除了您的意图的任何歧义,并且使您不必记住您引用了哪些变量值以及您没有引用哪些变量值。

为了直接解决您最近的问题,我建议在您的 call 中添加第 5 个参数来表示“a|-a”(对于 7za 或 wzzip),或者在循环中确定您是否应该使用 a-a 基于归档器是 7za 还是 wzzip

试试这个:

@echo off
setlocal

SET "ProcessLog=%USERPROFILE%\Documents\batch_files\%~n0_%jobLog%.txt"

:DetermineArchiveApp
:: Create specifics for ITD Logs collection
SET "ITDLogsLocation=%USERPROFILE%\Documents\fakeG"
SET "ITDLogsName=trace*%targetDate%.log"
SET "ITDLogsFilespec=%ITDLogsLocation%\%ITDLogsName%"

:: ********************************************************************************
:: * Check if server has WinZip or 7-Zip installed. setup environment variable    *
:: * accordingly with executable path and name, and with any required parameters. *
:: ********************************************************************************

for %%I in ("%PROGRAMFILES%" "%PROGRAMFILES(x86)%") do (
    for %%z in ("%%~I\WinZip\wzzip.exe" "%%~I\7-Zip\7z.exe") do (
        if exist "%%~z" set "zipCommand=%%~z"
    )
)

if not defined zipCommand set "zipCommand=%USERPROFILE%\Documents\batch_files\7za.exe"
if not exist "%zipCommand%" (
    echo Unable to locate 7z.exe, 7za.exe, or wzzip.exe
    exit /b 1
)


:ArchiveProcess
::Write the date and time of job starting to a log
>> "%ProcessLog%" (
    ECHO *****************************************************
    ECHO %DATE% %TIME% START
)

::Loop through the list that DIR gives for the given folder, and for each folder do zipCommand, excluding ITD\Data\AFS, and write to log
FOR /F "delims=" %%A IN (
    'DIR "%ITDLogsFilespec%" /B /S ^| find /v "logs3"'
) DO CALL :DoZip "%%~dpnA" "%%~fA" "%zipCommand%" "%ProcessLog%"

::Write end to log
>> "%ProcessLog%" (
    ECHO %DATE% %TIME% %~nx0 END
    ECHO *****************************************************
)

::End main runtime
goto :EOF


:DoZip
setlocal
SET "archiveName=%~1"
SET "SourceFileSpec=%~2"
SET "zipCommand=%~3"
SET "RunLog=%~4"

if "%zipCommand%"=="%zipCommand:7z=%" (
    rem then this is WinZip.
    set "switch=-a"
) else set "switch=a"

>>"%RunLog%" (

    echo Archiving %SourceFileSpec%...
    "%zipCommand%" %switch% "%archiveName%.zip" "%SourceFileSpec%"

    echo %TIME% Deleting %SourceFileSpec%...
    DEL "%SourceFileSpec%"

    echo;
)
GOTO :EOF

【讨论】:

  • 感谢您的回复!我不知道我可以在没有 3rd 方软件的情况下进行压缩,这很好。我尝试删除引号的原因是因为我尝试了您的解决方案,并且 CMD 吐出一个错误,我在修改此问题时遇到了很多:'""'(为可见性而添加的空格)未被识别为内部或外部命令, 可运行的程序或批处理文件...
  • 我通过回显 DoZip 中每个变量的值来调查问题所在,并看到了非常奇怪的结果...archiveName 成为运行脚本的 batch_files 目录中的第一个文件. SourceFileSpec 做了同样的事情。但是,runlog 正确指向 .cmd 的 .txt 日志。
  • 在你的脚本顶部(第 7 行)你有 SET ITDLogsFilespec=%ITDLogsLocation%\%ITDLogsName% 但在你的 for /f 循环中(第 41 行)你有 dir "LogsFilespec"。看起来您可能已经改变了对变量名的看法,但并没有在任何地方替换它。任何地方都没有实际的set LogsFilespec
  • 奇怪,其他版本的脚本都没有这个问题,我想知道这是否在原始帖子中。好的,所以除了 zipCommand 之外的所有变量现在都正确显示了。 zipcommand 保持空白
  • 在第 34 行附近尝试 echo zipCommand: %zipCommand%pause 看看那里是否存在逻辑问题。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2018-05-07
  • 1970-01-01
  • 2017-11-29
  • 2015-03-07
  • 1970-01-01
  • 2021-06-16
  • 1970-01-01
相关资源
最近更新 更多