web-dev-qa-db-ja.com

ループのネストされたバッチ

次のネストされたforループは私を怒らせます(Windows 7の場合):

@echo off
SetLocal EnableDelayedExpansion

set TESTDIRS=fast mid slow
set TD=src\test\resources\testsuite

for %%d in (%TESTDIRS%) do (
    set CTD=%TD%\%%d
    echo CTD: !CTD!
        REM Echos the expected path
    echo CTD: %CTD%
        REM Echos nothing -- understandable

    for /R !CTD! %%f in (*.fs) do (echo %%f)
        REM Echos nothing -- why?
    for /R src\test\resources\testsuite\fast %%f in (*.fs) do (echo %%f)
        REM Echos expected files
)

DelayedExpansion、call-statements、その他を無効にすることを含むさまざまなソリューションを試しましたが、内側のループが機能しませんでした。私はサブルーチン呼び出しによって内側のループを置き換えることができることを知っていますが、ネストされたループで動作させる方法がなければなりません。

20

pushd !CTD!popdを使用し、FOR /Rがデフォルトで現在のディレクトリを使用する場合はどうなりますか?

11
Ben Voigt

動作するネストされたループの例を挙げます。

@echo off
SetLocal

set B=alpha beta gamma
set A=eins zwo

FOR %%b in (%B%) do (
  FOR %%a in (%A% %%b) DO (
    echo %%b -^> %%a
  )
)

出力(少なくともWindows 7では)は

alpha -> eins
alpha -> zwo
alpha -> alpha
beta -> eins
beta -> zwo
beta -> beta
gamma -> eins
gamma -> zwo
gamma -> gamma

これは、ループ内の変数展開が括弧内で発生した場合(遅延展開がなくても)動作するというjebの観察をサポートします。

23

誰も言及していないので、ここにバッチサブルーチンとCALLコマンドを使用したソリューションがあります。

@echo off

set TESTDIRS=fast mid slow
set TD=src\test\resources\testsuite

for %%d in (%TESTDIRS%) do call :process_testdir %%d
goto :eof

:process_testdir
set CTD=%TD%\%1
echo CTD: %CTD%
    REM Echos the expected path

for /R %CTD% %%f in (*.fs) do (echo %%f)
    REM Echos as expected

goto :eof

GOTOはあまり人気がありませんが、バッチファイルはもともと制御フローにラベルを使用するように設計されていました。括弧で囲まれた制御構造の構文は後で追加されましたが、この質問はそれがどこで壊れているかの例です。この問題は、バッチサブルーチンに適しています。

12
Ryan Bemrose

明らかではありません! [〜#〜] for [〜#〜]!の特別な解析です。
A [〜#〜] for [〜#〜]コマンドは、エスケープ/特殊文字フェーズ(括弧を検出するため)の直後に解析されますが、結果としてパラメータとして遅延または%% var展開を使用します。

FOR %%a in (%%%%B) do (
  FOR %%a in (1) DO ( <<< this %%a will not replaced with %%B
      echo %%a - shows 1, because %%a is the name of the inner variable
      echo %%B - doesn't work
  )
)

また、これは機能しません:

set chars=abc
FOR /F "delims=!chars!" %%N in (bla) DO ....  

abおよびcをdelimsとして設定しませんが、chaおよびr代わりに。

EDIT:括弧内では、遅延展開は期待どおりに機能します。

set var=C:\temp
For %%a in (!var!) DO echo %%a

私はあなたがあなたの問題を解決するために関数を使わなければならないことを期待するでしょう。

5
jeb