2009-03-27 21 views
17

Ho un file batch che inizializza le variabili tramite SET all'interno di un ciclo for, per una serie di file su disco:variabili del file batch inizializzate in un ciclo for

for %%f in (%MYTARGETDIR%\*config.xml) do (
    SET TMPFILE=%%F.tmp 

    echo In loop %TMPFILE% 
) 

echo End loop %TMPFILE% 

quando si esegue questo in un comando di nuovo di zecca shell (senza TMPFILE definito) il ciclo In echo è vuoto, ma il ciclo finale echo no.

Quando si esegue una seconda volta, è già impostato e ne emette il valore, ignorando il set fino alla chiusura del ciclo.

Idee perché questo è e qual è la soluzione?

risposta

9

Questo perché il blocco() viene analizzato una sola volta, sostituisce% TMPFILE% prima di eseguire il ciclo.

+1

Grazie, ho appena visto setlocal ESPANSIONE ENABLEDELATA – theschmitzer

21

Per la cronaca, lo script corretto assomiglia a questo:

setlocal ENABLEDELAYEDEXPANSION 

for %%f in (%MYTARGETDIR%\*config.xml) do (

    SET TMPFILE=%%F.tmp 

    echo In loop !TMPFILE! 
) 

echo End loop %TMPFILE% 

Grazie Chris per il vostro aiuto.

16

Questo perché le variabili di ambiente vengono sostituite quando il comando è letto. Per il comando seguente:

for %%f in (%mytargetdir%\*config.xml) do (
    set tmpfile=%%f.tmp 
    echo In loop %tmpfile% 
) 

l'intero comando (da for alla parentesi chiusa) viene letto e sostituito prima dell'esecuzione.

è necessario utilizzare l'espansione ritardata, come ad esempio con:

@echo off 
    setlocal enableextensions enabledelayedexpansion 
    set full=/u01/users/pax 
:loop1 
    if not "!full:~-1!" == "/" (
     set full2=!full:~-1!!full2! 
     set full=!full:~,-1! 
     goto :loop1 
    ) 
    echo !full! 
    endlocal 

Quando si abilita ritardo di espansione, i marcatori "%" agire ancora come prima, ma è possibile utilizzare i "!" marcatori per fare l'espansione ritardata.

+2

Il tuo esempio avrebbe potuto essere un po 'più semplice :) – Lajcik

6

È inoltre possibile utilizzare CALL SET anziché un'espansione ritardata.

+0

Modo più leggibile! –

2

Normalmente, invoco CMD.EXE con/e: on e/v: su switch per abilitare estensioni di comando e espansione di variabile ritardata. Quindi tutti gli script batch che utilizzo sono codificati per verificare che l'espansione della variabile ritardata sia attivata.

Questa è la prima volta che sento parlare di SETLOCAL. Ho controllato con SETLOCAL /? e abbastanza sicuro! Questo è un tempo e un risparmiatore di codice per me.

Tuttavia, ho notato che le estensioni dei comandi devono essere abilitate in CMD.EXE prima che SETLOCAL riconosca l'opzione ENABLEDELAYEDEXPANSION. Questo è dall'output di SETLOCAL /?

If Command Extensions are enabled SETLOCAL changes as follows: 

SETLOCAL batch command now accepts optional arguments: 
     ENABLEEXTENSIONS/DISABLEEXTENSIONS 
      enable or disable command processor extensions. These 
      arguments takes precedence over the CMD /E:ON or /E:OFF 
      switches. See CMD /? for details. 
     ENABLEDELAYEDEXPANSION/DISABLEDELAYEDEXPANSION 
      enable or disable delayed environment variable 
      expansion. These arguments takes precedence over the CMD 
      /V:ON or /V:OFF switches. See CMD /? for details. 

Grazie a entrambi per questa preziosa risposta.