La boucle imbriquée suivante me rend fou (sous 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
)
J'ai essayé diverses solutions impliquant la désactivation de DelayedExpansion, des instructions d'appel et ainsi de suite, mais je n'ai jamais réussi à faire fonctionner la boucle interne. Je sais que je pourrais remplacer la boucle interne par un appel de sous-routine, mais il doit y avoir un moyen de la faire fonctionner avec des boucles imbriquées.
Et si vous utilisiez pushd !CTD!
et popd
, et laissez FOR /R
par défaut pour utiliser le répertoire courant?
Juste pour donner un exemple d'une boucle imbriquée qui fonctionne:
@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
)
)
La sortie (au moins sur Windows 7) est
alpha -> eins
alpha -> zwo
alpha -> alpha
beta -> eins
beta -> zwo
beta -> beta
gamma -> eins
gamma -> zwo
gamma -> gamma
Cela confirme l'observation de jeb selon laquelle l'expansion variable dans les boucles fonctionne si elles se produisent à l'intérieur des parenthèses (même sans expansion retardée).
Parce que personne ne l'a mentionné, voici la solution utilisant des sous-routines batch et la commande 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
Je sais que GOTO n'est pas très populaire, mais les fichiers de commandes ont été initialement conçus pour utiliser des étiquettes pour le flux de contrôle. La syntaxe de la structure de contrôle entre parenthèses a été ajoutée plus tard, et cette question est un exemple de la panne. Le problème se prête bien aux sous-programmes batch.
Ce n'est pas évident! C'est l'analyse spéciale de POUR !
Une commande POUR est analysée directement après la phase d'échappement/caractère spécial (pour détecter la parenthèse), mais par conséquent vous ne pouvez pas en utilisant une extension différée ou %% var comme paramètres.
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
)
)
Et cela ne peut pas fonctionner non plus:
set chars=abc
FOR /F "delims=!chars!" %%N in (bla) DO ....
ne définit pas a, b et c comme délimiteurs, mais !, c , h, a et r à la place.
EDIT: Dans les parenthèses, l'expansion retardée fonctionne comme prévu cependant:
set var=C:\temp
For %%a in (!var!) DO echo %%a
Je suppose que vous devez utiliser une fonction pour résoudre votre problème.
Citer la réponse de Malte Schwerhoff
Si vous ne voulez pas répéter B, vous pouvez simplement ajouter une instruction "if"
@echo off
SetLocal
set B=alpha beta gamma
set A=eins zwo
FOR %%b in (%B%) do (
FOR %%a in (%A% %%b) DO (
IF %%b NEQ %%a (
echo %%b -^> %%a
)
)
)
production:
alpha -> eins
alpha -> zwo
beta -> eins
beta -> zwo
gamma -> eins
gamma -> zwo