FOR ループについて誤解しています。/R オプションを使用しない限り、非常に高速です。(XP、Vista、Windows 7 でテスト済み)
20,000 個のファイルを含むテスト ディレクトリを作成し、次のスクリプトを実行しました。最初の 10 個のファイルが出力され、瞬く間に終了しました。
@echo off
set n=0
for %%F in (*) do (
echo %%F
set /a "n+=1, 1/(10-n)" 2>nul || goto :break
)
:break
意図的に 0 で割ってエラーを生成することで、10 個のファイルに達したことを検出します。遅延展開を使用してカウンターの値をテストすることもできましたが、ファイル名に文字が含まれていて遅延展開が有効になっていると%%F
、正しく印刷されません。!
したがって、あなたの考えに反して、単純な FOR は、ループを繰り返す前にすべての値を収集するわけではありません。
FOR /F バリアントと混同されている可能性がありますfor /f "delims=" %%F in ('dir /b /a-d *') do ...
。この場合、DIR コマンドは独自のシェルで実行され、FOR 反復の前に結果セット全体が取得されます。
FOR ソリューションで注意すべきことの 1 つは、FOR /R オプションを使用すると処理が遅くなる可能性があることです。/R オプションを使用するように上記のスクリプトを変更し、C:\
ルートで実行しました。見つかった最初の 10 個のファイルを非常に迅速に印刷しましたが、その後長時間ハングしたように見え、最終的に終了しました。これを証明する方法はわかりませんが、FOR ループは、C:
何もしていないにもかかわらず、ドライブ上のすべてのディレクトリを繰り返し処理して時間を無駄にしていると思います。
編集
元の質問に対する PA. のコメントを読みました。彼は優れたポイントを持っています - ファイルを正しい順序で返す暗黙のソート操作を実行するには、あるレベルで FOR と DIR の両方がディレクトリ全体を読み取らなければなりません。ただし、これは非常に低いレベルで行われていることも指摘しています。要点は、FOR コマンドは、反復を開始する前 (またはループから抜け出す前) に、すべての値が返されるのを待つ必要がないということです。
EDIT 2
FOR /F 動作は、祝福と呪いになる可能性があります。このアプリケーションの場合、それは呪いです。ただし、処理中にディレクトリの内容を変更する場合があります。FOR /F バリアントを使用すると、コマンドの開始後に行われた変更を確認できなくなります。単純な FOR コマンドは、繰り返しを開始した後に、ディレクトリの内容に変更が加えられることがあります。
FOR コマンドは反復をチャンクでバッファリングします - バッファ内にあるすべてのファイルを反復しますが、バッファが空で OS に戻って次のチャンクを取得すると、ディレクトリに発生した変更を確認できます. 動作を示すテスト スクリプトを次に示します。
@echo off
md myTemp
for /l %%N in (1001 1 6000) do echo a>myTemp\%%N.txt
for /f %%N in ('dir /b myTemp\* ^| find /c /v ""') do Echo Starting with %%N files
set cnt=0
(
for %%F in (myTemp\*) do (
echo %%F
del /q myTemp\* 2>nul
set /a cnt+=1
)
)> test_for.out
echo Only %cnt% files were listed by FOR
echo(
for /l %%N in (1001 1 6000) do echo a>myTemp\%%N.txt
for /f %%N in ('dir /b myTemp\* ^| find /c /v ""') do Echo Starting with %%N files
set cnt=0
(
for /f %%F in ('dir /b /a-d myTemp\*') do (
echo %%F
del /q myTemp\* 2>nul
set /a cnt+=1
)
)> test_for_f.out
echo All %cnt% files were listed by FOR /F
rd myTemp
結果は次のとおりです。
Starting with 5000 files
Only 743 files were listed by FOR
Starting with 5000 files
All 5000 files were listed by FOR /F
どちらのループも 5000 ファイルで始まり、最初の繰り返しの後にすべてのファイルを削除します。FOR /F は、開始時にディレクトリにあった 5000 個のファイル名すべてを引き続き処理します。FOR は、バッファーに収まる 743 個のファイル名のみを処理します。
注: Windows 7 で上記の結果を取得しました。Vista と XP でもテストしましたが、FOR ループに 743 ではなく 35 ファイルしかリストされていないことを除いて、結果は同じでした。