SET和SETLOCAL的问题

时间:2012-06-26 14:23:18

标签: batch-file

为了清楚说明,我已经查看了有关此主题的其他问题,但是他们要么没有解决这个问题,要么更经常不解决它。

我怀疑问题与嵌套的FOR循环和放置SETLOCAL的位置有关。

我所拥有的功能是检查文件是否在某段时间后被修改:

:CheckCopied result directory filename since -- returns whether the file has been modified in the time since 'since'
::                      -- result    [out]    - 0=FAIL, 1=SUCCESS
::                      -- directory [in]     - target directory
::                      -- filename [in]      - target filename
::                      -- since [in]         - the time the script started
SETLOCAL ENABLEEXTENSIONS ENABLEDELAYEDEXPANSION
set directory=%~2
set filename=%~3
set since=%~4

ECHO.CheckCopied directory="%directory%", filename=%filename%, since=%since%

FOR /F "tokens=1,2 delims= " %%d IN ('echo ^| dir "%directory%" ^| find "%filename%"') DO  (
    FOR /F "tokens=1,2 delims=:" %%h IN ('echo %%e') DO (
        ECHO Hours:  %since:~0,2%  vs  %%h
        ECHO Minutes:  %since:~3,2%  vs  %%i
        SET hours=!since:~0,2!
        SET minutes=%since:~3,2%
        ECHO hours=%hours%   minutes=%minutes%
        SET /A minutesSince=60*hours+minutes
        ECHO %minutesSince%
        SET hours=%%h
        SET minutes=%%i
        ECHO hours=%hours%   minutes=%minutes%
    )
)

EXIT /b

输出:

CheckCopied directory="<my directory>" filename=<my filename> since=15:18:34.98
Hours:  15  vs  15
Minutes:  18  vs  11
hours=  minutes=
ECHO is off.
hours=  minutes=

所以“SET hours =!since:~0,2!”似乎不起作用。

我试过了:

SET hours=!since:~0,2!
SET hours=%since:~0,2%
SET /A hours=!since:~0,2!
Every combination I could think of of SETLOCAL ENABLEDELAYEDEXPANSION and ENDLOCAL

我认为它与SETLOCAL有关,但我找不到神奇的组合......

修改

非常感谢jeb,下面。我按照他的建议重做了这个功能:

:CheckCopied result directory filename since -- returns whether the file has been modified in the last 5 minutes
::                      -- result    [out]    - 0=FAIL, 1=SUCCESS
::                      -- directory [in]     - target directory
::                      -- filename [in]      - target filename
::                      -- since [in]         - the time the script started
SETLOCAL ENABLEEXTENSIONS ENABLEDELAYEDEXPANSION
set directory=%~2
set filename=%~3
set since=%~4

ECHO.CheckCopied directory="%directory%", filename=%filename%, since=%since%

FOR /F "tokens=1,2 delims= " %%d IN ('echo ^| dir "%directory%" ^| find "%filename%"') DO (
    FOR /F "tokens=1,2 delims=:" %%h IN ('echo %%e') DO (
        ECHO Hours:  %since:~0,2%  vs  %%h
        ECHO Minutes:  %since:~3,2%  vs  %%i
        SET hours=!since:~0,2!
        SET minutes=!since:~3,2!
        ECHO hours=!hours!   minutes=!minutes!
        SET /A minutesSince=60*hours+minutes
        ECHO !minutesSince!
        SET /A hoursx=%%h
        SET /A minutesx=%%i
        ECHO hours=!hoursx!   minutes=!minutesx!
        SET /A minutesSincex=60*hoursx+minutesx
        ECHO !minutesSincex!
    )
)
ENDLOCAL

EXIT /b

总之,预期与必需:

SET hours=%since:~0,2%  ==> SET hours=!since:~0,2!
ECHO hours=%hours%      ==> ECHO hours=!hours!
SET hoursx=%%h          ==> SET /A hoursx=%%h

2 个答案:

答案 0 :(得分:1)

问题不在于SET的百分比扩张 这不会按预期工作,它会在解析块时扩展,而不是在执行时扩展 因此,您应该尝试延迟扩展。

答案 1 :(得分:0)

我学会了避免嵌套块并尽可能地写为短块。长或嵌套的块是调试的噩梦,并且块中的任何goto都会中断for循环。所以我经常编写一个子程序call:subRoutine,然后用goto:eof返回。子例程以常规方式工作:可以更改变量并使用%variable%访问它们。 {em> on 时Echo写入命令的实际参数。 GoTo也适用。您在调用另一个批处理文件时传递参数 - 子例程可以是单独的文件。然后call之后没有冒号。

当然,仍然存在使用块方便且需要延迟扩展的情况。我想在这里表明还有另一种方式。