2017-08-04 150 views
3

如果計數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 
) 
+3

'break'不成批處理。使用「goto」。 – SomethingDark

+0

批次中的'if'必須在一行中,變量必須使用'%%'擴展。 '如果j == 0'是一個語法錯誤 –

+0

謝謝,我只是不熟悉if語句的語法。你能提供確切的語法嗎?是否如果%% j = 0轉到這裏 –

回答

0

轉到將退出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 
+1

不使用調用運行不同的.bat會中斷批處理。 – LotPings

+0

我阻止複製(並忽略)該問題的.bat調用,添加「for break」示例邏輯。我已經進一步簡化了迴應。 –

3

這裏是你的批號改寫,評論說:

@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並且測量執行時間,並且一次又一次地在覈心/處理器的高速緩存中進行比較。

SETLOCALENDLOCAL內的使用情況循環,而不是外界使得在下半部中進行了描述,因爲這兩個命令來完成的所有操作的批處理文件執行完畢所需要的時間差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代碼運營商。在以單步模式運行應用程序時,也將其應用到標準庫函數strcmpstrtol中,更明確一點的是,處理器必須執行更多指令才能在批處理文件中運行比字符串比較更多的整數比較。

寫在Ç這第二個應用程序演示了完美的東西經常發生意外的批處理文件編寫者使用數字在批處理文件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與第三參數base0爲八進制數,其是因爲包含的無效解釋最終還執行作爲字符串而不是作爲整數比較數字8.有效的八進制數字只有0-7範圍內的數字。所以字符串到長整數的轉換失敗,因此與8相比,08的字符串比較被執行。

第三個比較14 EQU 14是作爲整數比較執行的,兩個數字都被解釋爲十進制數。

第四個比較014 EQU 014也作爲整數比較執行,但兩個數字都被解釋爲八進制。

第五次比較0x14 EQU 0x14再次作爲整數比較執行,但兩個數字被解釋爲十六進制解釋兩次20作爲輸出編號。

因此,建議儘可能使用運算符==以及不使用或使用明確圍繞的雙引號來在批處理文件中運行兩個值的字符串比較。

這是絕對沒用使用批處理文件來衡量==時間差與EQU,因爲Windows命令解釋程序所需要的時間來執行IF條件之前在批處理文件中的命令行解析爲許多倍量比較本身所需的時間,正如內部使用的編譯C/C++代碼所證明的那樣。

當然這也意味着使用==EQU對於完成批處理文件完成的任務所需的總時間並沒有給用戶帶來真正的區別。但除了執行時間使用==EQU之外的其他原因經常會有所不同。

+0

出於好奇,我以'if'!FileCount爲基準!「 ==「0」endlocal&goto完成行1,000,000次,在我的64位Win 7框中帶和不帶引號。結果是相同的(121,000毫秒)。我想這是預料之中的,因爲那是一個帶或不帶引號的字符串比較。所以我用'EQU'替換了未引用的版本'==',並再次獲得了相同的結果。我測量的唯一顯着差異是使用'!FileCount!'比使用'%FileCount%'慢10%(同樣,計時一百萬次)。看起來像是這個額外的傳球,如果一個巨大的標誌存在就會有所作爲。 –