vinduer - indlejret batch til sløjfer

Indlæg af Hanne Mølgaard Plasc

Problem



Følgende nested for-loop kører mig sur (på Windows 7):


@echo off
SetLocal EnableDelayedExpansion

set TESTDIRS=fast mid slow
set TD=src	est
esources	estsuite

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	est
esources	estsuitefast \%\%f in (*.fs) do (echo \%\%f)
        REM Echos expected files
)


Jeg har forsøgt forskellige løsninger, der involverer at deaktivere DelayedExpansion, call-statements og whatnot, men jeg har aldrig fået den indre loop arbejde. Jeg ved, at jeg kunne erstatte den indre loop ved et subrutineopkald, men der skal være en måde at få det til at arbejde med indlejrede sløjfer.

Bedste reference


Hvad hvis du brugte pushd !CTD! og popd, og lad FOR /R standard til at bruge den aktuelle mappe?

Andre referencer 1


Bare for at give et eksempel på en indlejret loop, der virker:


@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
  )
)


Udgangen (i hvert fald på Windows 7) er


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


Dette understøtter jebs observation om, at variabel ekspansion i sløjfer fungerer, hvis de forekommer inden for parentes (selv uden forsinket ekspansion).

Andre referencer 2


Fordi ingen har nævnt det, her er løsningen ved hjælp af batch subrutiner og kommandoen CALL.


@echo off

set TESTDIRS=fast mid slow
set TD=src	est
esources	estsuite

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


Jeg ved, at GOTO ikke er meget populær, men batch-filer blev oprindeligt designet til at bruge etiketter til kontrolflow. Den parenteserede kontrolstruktursyntax blev tilføjet senere, og dette spørgsmål er et eksempel på, hvor det bryder sammen. Problemet egner sig godt til batch-subrutiner.

Andre referencer 3


Det er ikke indlysende! Det er den særlige parsering af FOR !

En kommando FOR analyseres direkte efter escape/special character fase (til at opdage parentesen), men som følge heraf kan du ikke bruge forsinket eller \%\% var ekspansion som parametre.


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
  )
)


Og også dette kan ikke virke:


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


sætter ikke a , b og c som delims, men ! , c , h , en og r i stedet.


EDIT: I parenteserne virker den forsinkede ekspansion dog som forventet:


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


Jeg ville forvente, at du skal bruge en funktion til at løse dit problem.