Expansión retardada

Mantenido el

Actualizas una variable dentro de un bucle FOR o un bloque IF de un archivo por lotes, pero echo sigue mostrando el valor anterior. Es uno de los problemas más comunes al escribir archivos por lotes.

La solución es la expansión retardada de variables de entorno.

En resumen: añade setlocal enabledelayedexpansion y sustituye %variable% por !variable! dentro del bloque. Este artículo explica el momento de expansión que causa el problema y muestra cómo usar la expansión retardada con ejemplos.

El problema: las variables no se actualizan dentro de los bloques

Observa el siguiente archivo por lotes.

@echo off
setlocal

set COUNT=0
for %%f in (*.txt) do (
    set /a COUNT+=1
    echo Archivo %COUNT%: %%f
)
echo Total: %COUNT%

endlocal

El script intenta contar los archivos de texto, pero el resultado no es el esperado.

- □ ×
Ícono de la consola de comandos
Consola de comandos
Microsoft Windows [Version xx.x.xxxxx.xxx]
(c) 2026 Ribbit App Development All rights reserved.
 
C:\users\user>problem.cmd
Archivo 0: file1.txt
Archivo 0: file2.txt
Archivo 0: file3.txt
Total: 0
C:\users\user>

COUNT se muestra siempre como 0.

La causa: cuándo se expanden las variables

En los archivos por lotes, un bloque entre paréntesis () se analiza completo antes de ejecutarse. Durante el análisis, %variable% se sustituye por el valor que tenía antes de que empezara el bloque.

En el ejemplo anterior, %COUNT% se sustituye por 0 (su valor antes del bucle for), por lo que actualizarla dentro del bucle no tiene efecto visible.

rem Al analizar todo el bloque, %COUNT% se sustituye por 0
for %%f in (*.txt) do (
    set /a COUNT+=1
    echo Archivo 0: %%f    <- %COUNT% ya se ha convertido en 0
)

La solución: activar la expansión retardada

Activa la expansión retardada y usa !variable! en lugar de %variable%. Así la variable se expande en tiempo de ejecución.

Pasos

  1. Escribe setlocal enabledelayedexpansion
  2. Cambia las referencias a variables dentro del bloque por !variable!
@echo off
setlocal enabledelayedexpansion

set COUNT=0
for %%f in (*.txt) do (
    set /a COUNT+=1
    echo Archivo !COUNT!: %%f
)
echo Total: !COUNT!

endlocal
- □ ×
Ícono de la consola de comandos
Consola de comandos
Microsoft Windows [Version xx.x.xxxxx.xxx]
(c) 2026 Ribbit App Development All rights reserved.
 
C:\users\user>solution.cmd
Archivo 1: file1.txt
Archivo 2: file2.txt
Archivo 3: file3.txt
Total: 3
C:\users\user>
おすすめ書籍※ 広告を含む場合があります
中小企業経営者のためのRPA入門 RPA導入を成功させる方法

中小企業経営者のためのRPA入門 RPA導入を成功させる方法

60分でわかる! AIエージェント 超入門

60分でわかる! AIエージェント 超入門

コマンドラインの黒い画面が怖いんです。

コマンドラインの黒い画面が怖いんです。

知識・才能ゼロでもらく~に月10万円稼ぐ! よくわかるAI副業超入門

知識・才能ゼロでもらく~に月10万円稼ぐ! よくわかるAI副業超入門

Ahora COUNT se incrementa correctamente.

%variable% frente a !variable!

SintaxisSe expandeUso
%variable%Al analizarReferencias normales fuera de bloques
!variable!Al ejecutarVariables que cambian dentro de un bloque
Alcance de la expansión retardada

setlocal enabledelayedexpansion tiene efecto hasta el endlocal correspondiente (o hasta el final del archivo por lotes si no lo hay). Además, endlocal restaura las variables modificadas dentro de setlocal. Para activarla en todo el script, escríbela al principio del archivo.

El mismo problema en bloques IF

El mismo problema ocurre en bloques IF, no solo en bucles FOR.

@echo off
setlocal

set RESULT=NG

if exist "data.txt" (
    set RESULT=OK
    echo Resultado: %RESULT%
)

Aunque data.txt exista, se muestra Resultado: NG. Se corrige con la expansión retardada.

@echo off
setlocal enabledelayedexpansion

set RESULT=NG

if exist "data.txt" (
    set RESULT=OK
    echo Resultado: !RESULT!
)

Casos típicos que requieren expansión retardada

Numerar nombres de archivo

@echo off
setlocal enabledelayedexpansion

set NUM=0
for /f "delims=" %%f in ('dir /b /a-d *.jpg') do (
    set /a NUM+=1
    set PADDED=00!NUM!
    set PADDED=!PADDED:~-3!
    ren "%%f" "photo_!PADDED!.jpg"
)

echo Cambio de nombres finalizado.
endlocal
Recorrer archivos mientras se renombran

Si renombras archivos dentro de for %%f in (*.jpg), el bucle puede volver a procesar los archivos ya renombrados. Leer la salida de dir /b con for /f recorre la lista tal como estaba antes de empezar el bucle, lo que es más seguro.

Acumular valores en una variable

@echo off
setlocal enabledelayedexpansion

set ALL_FILES=
for %%f in (*.txt) do (
    set ALL_FILES=!ALL_FILES! %%f
)

echo Archivos encontrados:!ALL_FILES!
endlocal

Aspectos a tener en cuenta

Cadenas que contienen un signo de exclamación !

Con la expansión retardada activada, el ! de una cadena se interpreta como delimitador de variable. Ten cuidado con nombres de archivo y rutas que contengan !.

rem Con la expansión retardada activada, se pierde el "!" y se muestra C:\ImportantFiles
set PATH_WITH_BANG=C:\Important!Files
echo !PATH_WITH_BANG!
Cadenas con signos de exclamación

Con la expansión retardada activada, las cadenas que contienen ! pueden expandirse de forma inesperada. Si necesitas manejar este tipo de rutas, desactiva la expansión retardada en esa parte con setlocal disabledelayedexpansion o escapa el carácter como ^^!.

Úsala solo donde haga falta

La expansión retardada es potente, pero no se necesita en todas partes. Para referencias simples fuera de bloques, usa el %variable% habitual.

Resumen

ElementoDetalle
Cómo activarlasetlocal enabledelayedexpansion
Sintaxis de referencia!nombre_de_variable!
Dónde aparece el problemaDentro de bucles FOR y bloques IF
PrecauciónLas cadenas con ! pueden interpretarse mal

La expansión retardada es un conocimiento imprescindible para manejar variables correctamente dentro de bucles y bloques en archivos por lotes.

Artículos relacionados

Cuestionario

Problema de práctica

¿Qué afirmación describe correctamente cuándo se expanden %variable% y !variable!?

回答がサーバーに送信されることはありません
#Símbolo del sistema #Archivo por lotes #Expansión retardada #Variables #enabledelayedexpansion