Windows 批量退出for循环

Windows 批量退出for循环,windows,batch-file,for-loop,if-statement,Windows,Batch File,For Loop,If Statement,如果计数j达到0,我不想将留给循环 set /a j=3 for /R c:\dsd_imports\ad_and_deal %%i IN (*.*) DO ( MDI_import_ad_command.bat C:\DSD_IMPORTS\AD_AND_DEAL\%%~nxi MOVE %%i c:\dsd_imports\ad_and_deal\in_process set /a j=j-1 if j == 0 break ) 转到将退出代码。此外,必须使用延迟

如果计数
j
达到
0
,我不想将
留给
循环

set /a j=3
for /R c:\dsd_imports\ad_and_deal %%i IN (*.*) DO (
  MDI_import_ad_command.bat C:\DSD_IMPORTS\AD_AND_DEAL\%%~nxi
  MOVE %%i c:\dsd_imports\ad_and_deal\in_process
  set /a j=j-1
  if j == 0
     break
)

转到将退出代码。此外,必须使用延迟环境变量扩展来测试循环控制变量,因为FOR块在执行之前已完全展开%var%。大概是这样的:

setlocal enabledelayedexpansion
set /a j=3
for /R c:\dsd_imports\ad_and_deal %%i IN (*.*) DO (
  rem ... work that needs to be done ...
  set /a j=j-1
  if !j!==0 goto exit_for
)
:exit_for

以下是您的批处理代码重写和注释:

@echo off
rem Define environment variable FileCount with value 3.
set "FileCount=3"

rem Push path of current directory on stack and make specified directory
rem the current directory for everything up to command POPD.
pushd C:\dsd_imports\ad_and_deal

rem Process in directory specified above all non hidden files.

rem For each file call another batch file with name of current file.
rem Then move current file to subdirectory in_process and decrement
rem the file count variable by 1.

rem Enable delayed expansion which results also in creating a copy of
rem all environment variables and pushing current directory once again
rem on stack.

rem Run a string comparison (a few microseconds faster than an integer
rem comparison as environment variables are always of type string) to
rem determine if 3 files were already processed in which case the loop
rem is exited with a jump to a label below the loop.

rem In any case the previous environment must be restored with command
rem ENDLOCAL before the batch file execution continues on label Done or
rem with loop execution.

for %%I in (*) do (
    call MDI_import_ad_command.bat "%%I"
    move /Y "%%I" in_process\
    set /A FileCount-=1
    setlocal EnableDelayedExpansion
    if "!FileCount!" == "0" endlocal & goto Done
    endlocal
)

rem Delete the environment variable FileCount as no longer needed.
rem Then pop the previous current directory path from stack and make
rem this directory again the current directory for rest of batch file.

:Done
set "FileCount="
popd
我希望您不需要在
C:\dsd\u imports\ad\u和\u deal
中递归处理文件,因为这将导致在\u process
中处理子目录
中已处理的文件

要了解所使用的命令及其工作方式,请打开命令提示符窗口,在其中执行以下命令,并非常仔细地阅读为每个命令显示的所有帮助页面

  • 呼叫/?
  • echo/?
  • endlocal/?
  • goto/?
  • 如果/?
  • 移动/?
  • popd/?
  • pushd/?
  • rem/?
  • 设置/?
  • setlocal/?

有关将值与IF进行比较的额外信息

IFequal运算符
==
总是导致字符串比较,而运算符
equal
首先总是尝试整数比较,如果不可能,也会执行字符串比较,这可以通过以下方法证明:

@echo off
if 00 == 0  (echo 00 is equal 0 on using ==)  else (echo 00 is different 0 on using ==)
if 00 EQU 0 (echo 00 is equal 0 on using EQU) else (echo 00 is different 0 on using EQU)
执行时的输出为:

00 is different 0 on using ==
00 is equal 0 on using EQU
在批处理代码中,参数
周围的双引号!文件计数
0
可以安全地删除,但情况并非总是如此,但在这里确实如此

我添加双引号是为了让每个人都清楚,字符串是比较的,因为两个参数的双引号也是比较的

IF
=
运算符可以在C中编码,例如使用以下代码:

#包括
#包括
int main(int argc,char*args[]
{
如果(argc!=3)
{
puts(“错误:此比较演示需要两个参数。”);
返回2;
}
/*注意:使用的编译器添加到可执行文件的启动代码是
在调用函数main之前执行最有可能删除
参数字符串周围的双引号。
以“value”形式指定要比较的参数
带有双引号的参数*/
printf(“将%s与%s进行比较。\n”,参数[1],参数[2]);
if(strcmp(args[1],args[2])==0)
{
puts(“字符串相等”);
返回0;
}
puts(“字符串不同。”);
返回1;
}
因此,使用
“!FileCount!”==“0”
的区别是什么!文件计数!==0是指strcmp必须比较4字节和2字节,包括终止的空字节。这并没有真正的区别,因为可以通过修改上面的代码来证明这一点,并在循环中运行
strcmp
例如100.000.000次,然后在核心/处理器的缓存中反复测量执行时间

FOR循环内而不是在循环外使用SETLOCALENDLOCAL会使批处理文件执行完成所需的时间有所不同,因为这两个命令所执行的所有操作如本部分下半部分所述

因此,速度肯定会更快:

@echo off
setlocal EnableExtensions EnableDelayedExpansion
set "FileCount=3"
cd /D C:\dsd_imports\ad_and_deal

for %%I in (*) do (
    call MDI_import_ad_command.bat "%%I"
    move /Y "%%I" in_process\
    set /A FileCount-=1
    if !FileCount! == 0 goto Done
)

:Done
rem Add here other commands.

rem This command destroys the local copy of the environment variables which
rem means FileCount does not exist anymore if it did not exist before running
rem this batch file. It also restores the previous current directory changed
rem above with command CD.
endlocal
但是,如果找到的任何文件包含1个或多个感叹号,则此更快的批处理代码不起作用。原因是第一个
被解释为延迟环境变量引用的开始,如果没有第二个
,该引用将从文件名中删除被解释为延迟环境变量引用的结尾以及这两个变量之间的字符串
%%I
时,文件名中的code>很可能会被替换为nothing

通过运行此批处理文件,可以看到这种总是不需要的行为:

@echo off
echo File !1.txt>"%TEMP%\File !1.txt"
echo File !2!.txt>"%TEMP%\File !2!.txt"
echo File !XYZ! abc!.txt>"%TEMP%\File !XYZ! abc!.txt"

echo With delayed expansion disabled as by default:
echo/

for %%I in ("%TEMP%\File *") do echo "%%~nxI"

echo/
echo With delayed expansion enabled explicitly:
echo/

setlocal EnableExtensions EnableDelayedExpansion
for %%I in ("%TEMP%\File *") do echo "%%~nxI"
endlocal

del "%TEMP%\File *" >nul
echo/
pause
在Windows XP和Windows 7上执行的此批处理文件的输出为:

With delayed expansion disabled as by default:

"File !1.txt"
"File !2!.txt"
"File !XYZ! abc!.txt"

With delayed expansion enabled explicitly:

"File 1.txt"
"File .txt"
"File  abc.txt"
为确保完整性,操作员的等效C代码
EQU

#包括
#包括
#包括
int main(int argc,char*args[]
{
char*psEnd;
长整数1;
长内宽2;
如果(argc!=3)
{
puts(“错误:此比较演示需要两个参数。”);
返回2;
}
/*注意:使用的编译器添加到可执行文件的启动代码是
在调用函数main之前执行最有可能删除
参数字符串周围的双引号。
以“value”形式指定要比较的参数
带有双引号的参数*/
printf(“%s eq%s\n”,参数[1],参数[2]);
lArgument1=strtol(args[1],&psEnd,0);
如果(*psEnd!='\0')
{
if(strcmp(args[1],args[2])==0)
{
puts(“字符串相等”);
返回0;
}
puts(“字符串不同。”);
返回1;
}
lArgument2=strtol(args[2],&psEnd,0);
如果(*psEnd!='\0')
{
if(strcmp(args[1],args[2])==0)
{
puts(“字符串相等”);
返回0;
}
puts(“字符串不同。”);
返回1;
}
if(lArgument1==lArgument2)
{
printf(“整数%ld和%ld相等。\n”,lArgument1,lArgument2);
返回0;
}
printf(“整数%ld和%ld不同。\n”,lArgument1,lArgument2);
返回1;
}
在这里,我们已经看到,将用于演示
eq
行为的此C代码与上面用于演示
=
行为的C代码进行比较时,使用
eq
会导致整数比较
@echo off
equ.exe \"08\" \"08\"
equ.exe 08 8
equ.exe 14 14
equ.exe 014 014
equ.exe 0x14 0x14
equ.exe 0x14 20
equ.exe 0x14 \"20\"
"08" EQU "08"
The strings are equal.
08 EQU 8
The strings are different.
14 EQU 14
The integers 14 and 14 are equal.
014 EQU 014
The integers 12 and 12 are equal.
0x14 EQU 0x14
The integers 20 and 20 are equal.
0x14 EQU 20
The integers 20 and 20 are equal.
0x14 EQU "20"
The strings are different.