批量退出for循环
如果计数j
达到0
,我不想离开for
循环。批量退出for循环
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代码。此外,您必须使用延迟的环境变量扩展来测试您的循环控制变量,因为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
不使用调用运行不同的.bat会中断批处理。 – LotPings
我阻止复制(并忽略)该问题的.bat调用,添加“for break”示例逻辑。我已经进一步简化了回应。 –
这里是你的批号改写,评论说:
@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可以在Ç进行编码,例如用如下代码:
#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
所不同的是strcmp
具有比较4与2个字节包括终止空字节。这并没有真正的区别,因为可以通过修改上面的代码来证明它,并且在循环中运行例如100.000.000次的strcmp
并且测量执行时间,并且一次又一次地在核心/处理器的高速缓存中进行比较。
的SETLOCAL和ENDLOCAL的内的使用情况循环,而不是外界使得在下半部中进行了描述,因为这两个命令来完成的所有操作的批处理文件执行完毕所需要的时间差this answer。
那么快就肯定:
@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
时文件名将被替换为最有可能的内容。
这总是不受欢迎的行为可以通过运行这个批处理文件中可以看出:
@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
:
#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代码上面阐述了所引起的更多的CPU指令使用EQU
结果整数的比较比上做一个串正在执行使用==
比较==
行为比较该C代码运营商。在以单步模式运行应用程序时,也将其应用到标准库函数strcmp和strtol中,更明确一点的是,处理器必须执行更多指令才能在批处理文件中运行比字符串比较更多的整数比较。
写在Ç这第二个应用程序演示了完美的东西经常发生意外的批处理文件编写者使用数字在批处理文件1个或以上前导零上的字符串值与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\"
结果我与equ.exe
与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开始,并因此由函数strtol
与第三参数base
是0
为八进制数,其是因为包含的无效解释最终还执行作为字符串而不是作为整数比较数字8.有效的八进制数字只有0-7范围内的数字。所以字符串到长整数的转换失败,因此与8
相比,08
的字符串比较被执行。
第三个比较14 EQU 14
是作为整数比较执行的,两个数字都被解释为十进制数。
第四个比较014 EQU 014
也作为整数比较执行,但两个数字都被解释为八进制。
第五次比较0x14 EQU 0x14
再次作为整数比较执行,但两个数字被解释为十六进制解释两次20
作为输出编号。
因此,建议尽可能使用运算符==
以及不使用或使用明确围绕的双引号来在批处理文件中运行两个值的字符串比较。
这是绝对没用使用批处理文件来衡量==
时间差与EQU
,因为Windows命令解释程序所需要的时间来执行IF条件之前在批处理文件中的命令行解析为许多倍量比较本身所需的时间,正如内部使用的编译C/C++代码所证明的那样。
当然这也意味着使用==
或EQU
对于完成批处理文件完成的任务所需的总时间并没有给用户带来真正的区别。但除了执行时间使用==
或EQU
之外的其他原因经常会有所不同。
出于好奇,我以'if'!FileCount为基准!“ ==“0”endlocal&goto完成行1,000,000次,在我的64位Win 7框中带和不带引号。结果是相同的(121,000毫秒)。我想这是预料之中的,因为那是一个带或不带引号的字符串比较。所以我用'EQU'替换了未引用的版本'==',并再次获得了相同的结果。我测量的唯一显着差异是使用'!FileCount!'比使用'%FileCount%'慢10%(同样,计时一百万次)。看起来像是这个额外的传球,如果一个巨大的标志存在就会有所作为。 –
'break'不成批处理。使用“goto”。 – SomethingDark
批次中的'if'必须在一行中,变量必须使用'%%'扩展。 '如果j == 0'是一个语法错误 –
谢谢,我只是不熟悉if语句的语法。你能提供确切的语法吗?是否如果%% j = 0转到这里 –