批处理在第三次尝试时正确运行,但根本不在任务管理器中

Batch runs correctly on third attempt but not in task manager at all

我已经阅读了这里的各种答案并尝试了一些但没有成功。

我的问题是脚本 "log_copy_script.cmd",我在其中有几个子例程,但其中一个表现得很奇怪。该脚本旨在获取今天的日期,减去 1 年,然后开始删除 1 年前的文件夹。它有时有效。事实上,如果我通过命令行 运行 它会首先尝试删除一个名为 nothing "" 的文件夹,然后它会只尝试月份和日期 "MMDD",然后第三次它会正确地删除"YYYYMMDD"。任何进一步的后续时间都会成功,就好像缓存了一些东西一样。

此外,当我通过 Windows 任务计划程序 运行 执行此操作时,它会 运行 并记录到我的日志文件,但每次它都会尝试删除 "" 空白。

有人知道这里发生了什么吗?谢谢。 :-/

REM Get IP and Vol Name from file, define variables
for /f "delims=" %%x in (C:/SystemHealthScripts/ip_address.txt) do set IP_ADDRESS=%%x
for /f "delims=" %%x in (C:/SystemHealthScripts/vol_name.txt) do set VOL_NAME=%%x
set MAINDIR="\%IP_ADDRESS%%VOL_NAME%"
set SUBDIR="\%IP_ADDRESS%%VOL_NAME%\%LOG_DATE%"
set LOGFILE="\%IP_ADDRESS%%VOL_NAME%\log.txt"

if [%1]==[delete_oldest] (

  REM Format date
  for /f "tokens=1,2,3,4 delims=/ " %%a in ("%date%") do set month=%%b&set year=%%c&set day=%%a
  set LOG_DATE=%year%%month%%day%

  set /A "DEL_YEAR=year-1"
  set DEL_DATE=%DEL_YEAR%%month%%day%

  REM Basic validation (Greater than or equal to 20160101 then valid date)
  if [%DEL_DATE%] GEQ [20160101] (
    call echo "%LOG_DATE% %LOG_TIME%: Deleting date '%DEL_DATE%' started" >> %LOGFILE%
    call rmdir /s /q %MAINDIR%\%DEL_DATE%
    call echo "%LOG_DATE% %LOG_TIME%: Deleting date '%DEL_DATE%' finished" >> %LOGFILE%

  ) else (
    call echo "%LOG_DATE% %LOG_TIME%: ERROR in deleting date '%DEL_DATE%', validation not met!" >> %LOGFILE%
  )
)

由于您没有将对 cmd 有意义的字符分配给您的变量,因此您应该安全地在 scipt 的顶部(第一行)插入一行 setlocal enabledelayedexpansion

对于任何代码块(带括号的代码),首先解析该块 - 解析过程的一部分是用它的 then- 替换 ANY %var% 变量当前值。由于您在代码块中分配了实例 month,因此它在第一个 运行 上的值是 nothing - setlocal 不存在,第一个 运行 上 month 的值将用作第二个上的初始值,依此类推。

setlocal enabledelayedexpansion 做了两件事。首先,当批次结束时,环境恢复到原来的设置。所有更改都被取消,因此在任何 运行 中分配或更改的任何值都是 "reset".

它做的第二件事是允许语法 !var! 访问变量 的值,因为它在块 内发生变化(通常是由于for 循环,也是 if/else 操作的结果)。

所以 - 添加 setlocal enabledelayedexpansion 并替换 any 变量,其值在块内从 %var% 更改为 !var!

这被称为 "delayed expansion" - 关于这个主题有数百个项目。使用 search 表示很多很多例子。

一种替代方法,使用任何延迟扩展。

@echo off
REM Get IP and Vol Name from file, define variables
for /f "usebackq delims=" %%x in ("C:\SystemHealthScripts\ip_address.txt") do set "IP_ADDRESS=%%x"
for /f "usebackq delims=" %%x in ("C:\SystemHealthScripts\vol_name.txt") do set "VOL_NAME=%%x"
set "MAINDIR=\%IP_ADDRESS%%VOL_NAME%"
set "SUBDIR=\%IP_ADDRESS%%VOL_NAME%\%LOG_DATE%"
set "LOGFILE=\%IP_ADDRESS%%VOL_NAME%\log.txt"

if "%1"=="delete_oldest" CALL :delete_oldest

GOTO :EOF

:delete_oldest
REM Format date
for /f "tokens=1,2,3,4 delims=/ " %%a in ("%date%") do (
    set "month=%%b"
    set "year=%%c"
    set "day=%%a"
)
set "LOG_DATE=%year%%month%%day%"

set /A "DEL_YEAR=year-1"
set "DEL_DATE=%DEL_YEAR%%month%%day%"

REM Basic validation (Greater than or equal to 20160101 then valid date)
if %DEL_DATE% GEQ 20160101 (
    echo "%LOG_DATE% %LOG_TIME%: Deleting date '%DEL_DATE%' started" >> "%LOGFILE%"
    rmdir /s /q "%MAINDIR%\%DEL_DATE%"
    echo "%LOG_DATE% %LOG_TIME%: Deleting date '%DEL_DATE%' finished" >> "%LOGFILE%"

) else (
    echo "%LOG_DATE% %LOG_TIME%: ERROR in deleting date '%DEL_DATE%', validation not met!" >> "%LOGFILE%"
)