批量退出for循环

如果计数j达到0我不想离开for循环。

 set /aj=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 %%ic:\dsd_imports\ad_and_deal\in_process set /aj=j-1 if j == 0 break ) 

Solutions Collecting From Web of "批量退出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_imports\ad_and_deal中的文件,因为这样会导致处理子目录in_process已经处理的文件。

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

  • call /?
  • echo /?
  • endlocal /?
  • goto /?
  • if /?
  • move /?
  • popd /?
  • pushd /?
  • rem /?
  • set /?
  • setlocal /?

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

IF等于运算符==结果总是在字符串比较中,而运算符EQU首先总是尝试一个整数比较,并且如果这不是可能的,则执行字符串比较,因为它可以证明:

 @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 

在参数周围的双引号之上的批处理代码!FileCount!0可以安全地删除,这并不总是这样,但在这里。

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

IF==运算符可以用C编码,例如:

 #include <stdio.h> #include <string.h> int main(int argc, char* args[]) { if(argc != 3) { puts("Error: This compare demo requires exactly two parameters."); return 2; } /* Note: The startup code added by used compiler to executable being executed before calling function main removes most likely the surrounding double quotes on the argument strings. Specify the arguments in form \"value\" to compare the arguments with surrounding double quotes. */ printf("Compare %s with %s.\n",args[1],args[2]); if(strcmp(args[1],args[2]) == 0) { puts("The strings are equal."); return 0; } puts("The strings are different."); return 1; } 

所以使用"!FileCount!" == "0"的区别 "!FileCount!" == "0"!FileCount! == 0 !FileCount! == 0表示strcmp必须比较4个字节和2个字节,包括终止空字节。 这并没有真正的区别,因为通过修改上面的代码可以证明这一点,并且在一个循环中运行strcmp例如100.000.000次,并测量执行时间,一次又一次地在核心/处理器的缓存中进行比较。

FOR循环中使用SETLOCALENDLOCAL而不是在外使得批处理文件执行完成所需的时间有所不同,因为在这个答案的下半部分描述了由这两个命令完成的所有操作。

所以更快将是肯定的:

 @echo off setlocal EnableExtensions EnableDelayedExpansion set "FileCount=3" cd /DC:\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 

但是,如果FOR找到的任何文件包含1个或更多感叹号,则此快速批处理代码不起作用。 原因是第一! 在一个文件名被解释为一个延迟的环境变量参考的开始,如果没有第二个从文件名删除! 这被解释为延迟的环境变量引用的结束以及这两者之间的字符串! 在调用另一个批处理文件之前,在扩展%%I ,文件名中的内容很可能会被替换。

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

 @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" 

为了完整性,运算符EQU的等效C代码:

 #include <stdio.h> #include <stdlib.h> #include <string.h> int main(int argc, char* args[]) { char* psEnd; long int lArgument1; long int lArgument2; if(argc != 3) { puts("Error: This compare demo requires exactly two parameters."); return 2; } /* Note: The startup code added by used compiler to executable being executed before calling function main removes most likely the surrounding double quotes on the argument strings. Specify the arguments in form \"value\" to compare the arguments with surrounding double quotes. */ printf("%s EQU %s\n",args[1],args[2]); lArgument1 = strtol(args[1],&psEnd,0); if(*psEnd != '\0') { if(strcmp(args[1],args[2]) == 0) { puts("The strings are equal."); return 0; } puts("The strings are different."); return 1; } lArgument2 = strtol(args[2],&psEnd,0); if(*psEnd != '\0') { if(strcmp(args[1],args[2]) == 0) { puts("The strings are equal."); return 0; } puts("The strings are different."); return 1; } if(lArgument1 == lArgument2) { printf("The integers %ld and %ld are equal.\n",lArgument1,lArgument2); return 0; } printf("The integers %ld and %ld are different.\n",lArgument1,lArgument2); return 1; } 

在这里可以看到,比较这个用于演示EQU行为的C代码与上面的C代码来演示==行为,使用EQU导致的更多的CPU指令执行的整数比较比执行更多的CPU指令比比较使用==运营商。 在单步模式下运行的应用程序也运行到标准库函数strcmp和strtol中,处理器必须执行更多的指令才能在批处理文件中执行比字符串比较更多的指令。

C语言编写的这个第二个应用程序展示了批处理文件编写者使用批处理文件中的一个或多个前导零的数字与EQU进行比较或在算术表达式中使用它们(即在set /A之后的字符串中)时常常出乎意料的情况。

例如,将以上代码编译到equ.exe并运行以下命令:

 @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\" 

用gpp 4.7.3(DJGPP软件包)编译得到的结果是:

 "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. 

第一个比较"08" EQU "08"是作为字符串比较执行的,因为"在这两个参数中。

第二个比较08 EQU 8最后也作为字符串执行,而不是整数比较,因为第一个参数以前导0开始,因此被第三个参数base0的函数strtol解释为八进制数,由于包含数字8 。有效的八进制数字只有0-7范围内的数字。 所以字符串到长整数的转换失败了,因此,字符串比较执行088比较。

第三比较14 EQU 14以整数比较执行,两个数字都被解释为十进制数。

第四比较014 EQU 014也被执行为整数比较,但是这两个数字被解释为八进制。

第五个比较0x14 EQU 0x14再次作为整数比较执行,但是这两个数字都被解释为十六进制,解释了两次20作为输出数字。

所以,建议在批处理文件中尽可能使用运算符==和不运行或使用明确围绕的双引号来运行两个值的字符串比较。

使用批处理文件测量==EQU时间差是绝对没有用的,因为Windows命令解释器在执行IF条件之前解析批处理文件中的命令行所需的时间是比较本身所需的时间量的许多倍如内部使用的编译C / C ++代码所示。

当然,这也意味着使用==EQU对于完成批处理文件完成任务所需的总时间,并没有给用户带来真正的改变。 但是除了使用==EQU执行时间以外,其他的原因通常是不同的。

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

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