批处理函数无法写入日志变量

Batch Function can't write to log variable

我有一个批处理脚本,它进入文件夹的子文件夹(不包括一个文件夹)获取 .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-Zipz.exe"
SET Path7Zip_32bit="C:\Program Files (x86)-Zipz.exe"
SET Path7Zip_true="C:\Users\Me\Documents\batch_filesza.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

我从 c​​md NOW 得到的错误是:

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

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

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

"C:\Users\Me\Documents\batch_filesza.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.

我看到的最大不同是,在您成功的单行文章中,您正确地引用了一些东西;而在调用者和子例程中的 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%"。这消除了您的意图的任何歧义,并使您不必记住您引用了哪些变量值而没有引用。

为了直接解决您最近的问题,我建议为 "a|-a"(对于 7za 或 wzzip)向您的 call 添加第 5 个参数,或者在循环中确定您是否应该使用 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-Zipz.exe") do (
        if exist "%%~z" set "zipCommand=%%~z"
    )
)

if not defined zipCommand set "zipCommand=%USERPROFILE%\Documents\batch_filesza.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