3

FOR ループを使用して複数のファイルを作成するために、次のバッチ ファイルを作成しました。

@エコーオフ  
cls  
FOR /L %%i IN (1 1 10) DO (  
    echo.> file%%i.txt  
    IF ERRORLEVEL 0 echo ファイル 'file%%i.txt' が正常に作成されました。  
)  
dir /b *.txt  
FOR %%i IN (*.txt) DO (  
    echo.> file%%i.txt
    IF ERRORLEVEL 0 echo ファイル 'file%%i.txt' が正常に作成されました。  
)

ここでは、最初の FOR ループで 10 個のファイル (つまりfile1.txt.... ) が作成されます。 2 番目の FOR ループでは、これらのファイルを使用して、次の新しいファイルの名前を組み立てました。(つまり... ) file10.txt
filefile1.txt.txtfilefile10.txt.txt

しかし、余分なファイルが作成されています: この余分なファイルの作成を引き起こしている論理的な問題は何ですか?filefilefile1.txt.txt.txt

4

3 に答える 3

5

EDITED - 私はそれを適切に説明していないようで、人々はそれがどのように機能するかを理解していません. 私のせいです。私はそれをよりよく説明しようとします。

その理由は、for コマンドが内部で動作する方法にあります。

for var in (files)に達すると、ディレクトリがチェックされ、一致するファイルがあり、処理する必要があるかどうかが確認されます。

次に、forコマンド (実際には cmd) がディレクトリ クエリを発行して、ファイルを列挙します。このクエリは、セット内の最初のファイルのみを返します。コマンドのファイル マスクに一致する追加のファイルがある場合for、処理するファイルがまだあることを呼び出し元 (cmd) に示すフラグが設定されますが、残りのファイルのリストはまだ取得されていません

内部のコードの実行がfor反復の最後に達し、読み取り待ちのファイルがある場合、クエリが送信され、処理待ちのファイルの残りforのリストを取得し、ファイル選択に一致します。

システムは、残っているファイルのリストでバッファを埋めます。その時点で、ファイルのリストがバッファで完全に読み取られるほど短い場合、クエリは繰り返されません。ファイルのリストがバッファに収まらないほど大きい場合、部分的なリストが取得され、取得されたリスト内のファイルが処理されると、処理するファイルをさらに取得するためにクエリが再度送信されます。

バッファ内のファイル数は、ファイル名の長さによって異なります。ファイル名が短くなり、バッファ内のファイルが増え、ファイルシステムへのクエリが少なくなります。

この動作 (最初のファイル処理の最後にファイルの残りのリストを取得する) は、ファイルのクエリが保留中のファイルがあることを返した場合にのみ実行されます。1 つのクエリがそのフラグを返さない場合、それ以上のファイルは取得されません。

例外

NTFS で作業している場合、コマンドで処理された最後のファイルよりもアルファベット順で大きい場合にのみ、ファイルは「再クエリ」に含まれますfor

FAT で動作している場合、クエリには、for名前に関係なく、コマンド ファイルの選択に一致する、生成されたすべての新しいファイルが含まれます。はい、無限ループに陥る可能性があります。(テストでは、システム バッファは 1 つのファイル名のみを取得し、反復ごとに再クエリを実行します)。あなたが試すことができます

break > a.txt && cmd /v:on /c "for %f in (*.txt) do break > !random!.txt"

すべてのテストは、Windows 7 64 ビット、NTFS および FAT32 パーティション (これは USB ドライブ上) で行われました。他の構成をテストする方法はありません。誰かが異なる動作を見つけた場合は、コメントしてください。

詳細については、ZwQueryDirectoryFile

于 2013-10-31T11:43:06.597 に答える
3

理由はわかりませんが... IN (*.txt) ...、2 番目のforループに書き込むと、ループの本体内で作成されたばかりのファイルを見つけようとしています。

それを排除するために、フィルターをもう少し具体的にします。

FOR %%i IN (file??.txt) DO (

これを実行したところ、予想どおり 20 個のファイルしか作成されませんでした。

于 2013-10-31T11:23:06.183 に答える
3

adarshr が言ったように、2 番目の FOR ループは、新しく作成されたファイルも見つけることができます。
ループの本体が実行される前に dir の結果が完全にフェッチされるため、コマンドで FOR/F を使用することでこれを回避できます。

...
FOR /F "delims=" %%i IN ('dir /b *.txt') DO (  
    echo.> file%%i.txt
    IF ERRORLEVEL 0 echo Successfully created file 'file%%i.txt'.  
)
于 2013-10-31T11:28:09.577 に答える