ここにあなたのバッチコードを書き換えとコメントしている:
@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等しい演算子オペレータ一方、文字列比較で常に==
結果を比較に関する追加情報これを用いて証明することができるように常に整数の比較を試み、これが可能でない場合、文字列比較を行う第1 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
の二重引用符は安全に削除できますが、必ずしもそうではありませんが、ここではそうです。
二重引用符を追加して、両方の引数の二重引用符も比較するため、文字列が比較されるすべての人にわかりやすくしました。
このコードで、例えばCで符号化することができる 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バイトを比較しなければならないことです終了nullバイト上記のコードを変更してループ内でstrcmp
(例:100.000.000)を実行することで実証されたように実際の違いはありません。また、コア/プロセッサのキャッシュで比較を繰り返し実行するための実行時間を測定します。
の下半分に記載されているように外部ループはなくFOR 内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
しかし FOR によって発見されたファイルは、1以上の感嘆符が含まれている場合は、この高速化バッチコードは動作しません。その理由は、ファイル名中の最初の!
が、遅延環境変数参照の終わりと解釈される第2の!
とその2つの間の文字列であると解釈されない場合、ファイル名から削除される遅延環境変数参照の開始として解釈されるからです。!
ファイル名は、他のバッチファイルを呼び出す前に、%%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にも実行すると、プロセッサは文字列比較よりもバッチファイルで整数比較を実行するためにさらに多くの命令を実行する必要があります。
Cに書かれたこの第二のアプリケーションは、文字列、すなわち、EQU
との値を比較または算術式でそれらを使用してバッチファイルで1つの以上の先頭ゼロで数字を使用してバッチファイルライターのため、多くの場合、予期しない何が起こるかを完璧に証明します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\"
IがGPP 4.7.3(DJGPPパッケージ)でコンパイルequ.exe
で得た結果は次のとおり
"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"
が文字列比較として実行されます。最初の引数は、先頭の0で始まり、したがってため含有する第三のパラメータbase
が無効で8進数として0
された状態で機能strtol
によって解釈されるため
第2の比較08 EQU 8
は、最終的に、文字列としてではなく、整数の比較として実行されます有効な8進数には、0〜7の範囲の数字しかありません。そのため、文字列から長整数への変換に失敗し、その理由から、8
と比較して08
の文字列比較が実行されます。
第3の比較14 EQU 14
は、両方の数値が10進数で解釈される整数比較として実行されます。
第4の比較014 EQU 014
は整数比較としても実行されますが、両方の数値は8進数で解釈されます。
第5の比較0x14 EQU 0x14
が整数比較として再度実行されますが、両方の数値が出力番号として2回20
を説明する16進数で解釈されます。
したがって、可能であればオペレータ==
を使用し、明示的に囲む二重引用符を使用しないで、または二重引用符を明示的に使用して、バッチファイル内の2つの値の文字列比較を常に実行することをお勧めします。
IF条件を実行する前に、バッチファイル内のコマンドラインを解析するために、Windowsのコマンド・インタプリタによって必要な時間は、多く倍の量であるため、バッチファイルを使用してEQU
対==
の時間差を測定することが絶対に無用です内部で使用されるコンパイル済みC/C++コードで示されているように、それ自体を比較するのに必要な時間がかかります。
もちろん、==
またはEQU
を使用しても、バッチファイルで行われたタスクを実行するのに必要な合計時間に関して実際の違いはありません。しかし、実行時間以外の理由で==
またはEQU
を使用すると、多くの場合違いがあります。
'break 'は何もしません。 'goto'を使ってください。 – SomethingDark
バッチの 'if'は一行でなければならず、変数は' %% 'を使って展開しなければなりません。 'j == 0'が構文エラーの場合 –
ありがとうございます。私はif文の構文に慣れていません。あなたは正確な構文を提供できますか?もし%% j = 0 gotoならば –