Subrutinas y valores de retorno

Mantenido el

Cuando un archivo por lotes empieza a crecer, escribir el mismo procesamiento una y otra vez resulta engorroso y además es un foco de errores. En esos casos resultan útiles las subrutinas (pseudofunciones).

Los archivos por lotes no tienen una sintaxis de «definición de funciones» como otros lenguajes de programación, pero con CALL :nombre_de_etiqueta se puede lograr una estructura muy parecida a una función. En este artículo se explica paso a paso, desde cómo crear una subrutina básica hasta cómo pasar argumentos y devolver números y cadenas.

Estructura básica de una subrutina

Una subrutina se compone de los siguientes elementos.

ElementoDescripción
CALL :nombre_de_etiquetaLlama a la subrutina
:nombre_de_etiquetaEtiqueta que indica el punto de inicio de la subrutina
EXIT /B código_de_salidaRegresa de la subrutina al código que la llamó
GOTO :EOFEquivale a EXIT /B (sin especificar código de salida). Finaliza la subrutina

Para separar el procesamiento principal de las subrutinas, el punto importante es colocar GOTO :EOF al final del código principal. Sin él, la ejecución continúa y pasa directamente al código de la subrutina.

@echo off
setlocal

CALL :GREET "García"
CALL :GREET "López"

GOTO :EOF

:GREET
echo ¡Hola, %~1!
EXIT /B 0
- □ ×
Í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>basic-sub.cmd
¡Hola, García!
¡Hola, López!
C:\users\user>
Acerca de GOTO :EOF

:EOF es una etiqueta especial que representa el final del archivo. GOTO :EOF finaliza la subrutina igual que EXIT /B, pero no permite especificar un código de salida y se conserva tal cual el ERRORLEVEL anterior. Si desea especificar un código de salida, use EXIT /B N. Al final del código principal se puede usar cualquiera de los dos.

Ubicación de las subrutinas

Las subrutinas funcionan estén donde estén en el archivo, pero lo habitual es escribirlas todas juntas después del procesamiento principal (tras GOTO :EOF). Esto mejora la legibilidad del código.

Cómo pasar argumentos a una subrutina

Se pueden pasar argumentos a continuación del nombre de la etiqueta, como en CALL :nombre_de_etiqueta argumento1 argumento2 .... Dentro de la subrutina se accede a ellos con %1, %2…

NotaciónSignificado
%1Primer argumento (incluye las comillas)
%~1Primer argumento (sin las comillas del principio y del final)
%2Segundo argumento
@echo off
setlocal

CALL :SHOW_INFO "López" "Madrid" 30

GOTO :EOF

:SHOW_INFO
echo Nombre: %~1
echo Ciudad: %~2
echo Edad: %3
EXIT /B 0
- □ ×
Í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>args-demo.cmd
Nombre: López
Ciudad: Madrid
Edad: 30
C:\users\user>
おすすめ書籍※ 広告を含む場合があります
中小企業経営者のためのRPA入門 RPA導入を成功させる方法

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

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

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

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

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

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

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

Diferencia entre %~1 y %1

Si se pasa un argumento encerrado entre comillas, como "López", con %1 se obtiene "López" (con comillas) y con %~1 se obtiene López (sin comillas). Al trabajar con cadenas es más seguro usar %~1.

Valores de retorno numéricos (ERRORLEVEL)

Para devolver un número desde una subrutina, se especifica un código de salida (N) con EXIT /B N. En el código que la llama, el valor se recibe con %ERRORLEVEL% o con IF ERRORLEVEL N.

Por convención, se devuelve 0 en caso de éxito y un valor de 1 o superior en caso de error o fallo.

@echo off
setlocal

CALL :IS_EVEN 4
IF %ERRORLEVEL% EQU 0 (
    echo 4 es par.
) ELSE (
    echo 4 es impar.
)

CALL :IS_EVEN 7
IF %ERRORLEVEL% EQU 0 (
    echo 7 es par.
) ELSE (
    echo 7 es impar.
)

GOTO :EOF

:IS_EVEN
set /a CHECK=%1 %% 2
EXIT /B %CHECK%
- □ ×
Í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>numeric-return.cmd
4 es par.
7 es impar.
C:\users\user>
Significado de %%

El %% de set /a CHECK=%1 %% 2 es el carácter de escape que representa el propio símbolo % dentro de un archivo por lotes. %1 %% 2 calcula «el resto de dividir %1 entre 2». Si el resto es 0, es par; si es 1, es impar.

Código de salida de EXIT /B

Si no se especifica un número en EXIT /B, se devuelve tal cual el ERRORLEVEL de ese momento. Para evitar que se devuelva un valor no deseado, se recomienda especificarlo de forma explícita, como en EXIT /B 0.

Valores de retorno de cadenas (truco de endlocal & set)

A diferencia de los números, devolver una cadena es algo más complicado. Si se usa setlocal dentro de la subrutina, el ámbito de las variables se cierra, de modo que al llamar a endlocal todas las variables de la subrutina desaparecen.

La solución a este problema es la técnica de combinar endlocal & set nombre_de_variable=valor en una sola línea.

Por qué funciona al combinarlo en una sola línea

El Símbolo del sistema analiza la línea completa antes de ejecutarla. Al escribir endlocal & set RESULT=valor, el valor del lado derecho de set se analiza en el estado anterior a la ejecución de endlocal. Es decir, después de que el valor de la variable de la subrutina se expande en el lado derecho de set, se ejecuta endlocal y la variable queda definida en el ámbito del código que llamó.

@echo off
setlocal

CALL :GET_GREETING "García" RESULT
echo %RESULT%

GOTO :EOF

:GET_GREETING
setlocal
set NAME=%~1
set GREETING=¡Hola, %NAME%!
endlocal & set "%~2=%GREETING%"
EXIT /B 0
- □ ×
Í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>string-return.cmd
¡Hola, García!
C:\users\user>

En este patrón, se pasa en el segundo argumento (%~2) el nombre de la variable donde se almacenará el valor de retorno. Como el código que llama puede elegir libremente el nombre de la variable, se gana versatilidad.

Patrón con un nombre de variable fijo

En lugar de pasar el nombre de la variable como argumento, también se usa mucho, por su sencillez, un nombre de variable fijo (por ejemplo, RESULT).

@echo off
setlocal

CALL :FORMAT_DATE
echo Fecha con formato: %RESULT%

GOTO :EOF

:FORMAT_DATE
setlocal
set YEAR=%DATE:~0,4%
set MONTH=%DATE:~5,2%
set DAY=%DATE:~8,2%
set LOCAL_RESULT=%YEAR%%MONTH%%DAY%
endlocal & set "RESULT=%LOCAL_RESULT%"
EXIT /B 0
- □ ×
Í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>fixed-return.cmd
Fecha con formato: 20260424
C:\users\user>
El formato de %DATE% varía según el entorno

El formato de %DATE% cambia según la configuración regional. El ejemplo anterior asume el formato yyyy/MM/dd (por ejemplo, 2026/04/24), por lo que en otros entornos la fecha no se extraerá correctamente. Para saber cómo obtener la fecha de forma independiente del entorno, consulte el artículo relacionado sobre cómo obtener la fecha y la hora.

Debe escribirse en una sola línea

endlocal & set nombre_de_variable=valor debe escribirse siempre en una sola línea. Si se divide en dos líneas, las variables de la subrutina desaparecen en el momento de endlocal y el valor de set queda vacío.

Encierre el valor entre comillas

Cuando otro comando sigue en la misma línea (set nombre_de_variable=valor & ...), el espacio anterior al & pasa a formar parte del valor. Además, si el valor contiene caracteres especiales como & o ), puede producirse un error de sintaxis. Encerrar todo entre comillas, como en set "nombre_de_variable=valor", permite evitarlo. Como el manejo de valores que contienen % o ! es complejo, con esta técnica lo más seguro es limitarse a devolver cadenas sencillas de caracteres alfanuméricos.

Devolver varias cadenas

Al colocar varios set en una misma línea, como en endlocal & set "%~2=%VAL1%" & set "%~3=%VAL2%", se pueden devolver varios valores a la vez. Resulta útil combinarlo con el patrón de recibir los nombres de variable por argumento.

Ejemplo práctico: subrutina para comprobar la existencia de archivos

Como ejemplo práctico que combina lo visto hasta ahora, se muestra una subrutina que comprueba la existencia de varios archivos y devuelve el número de archivos que faltan.

@echo off
setlocal

CALL :CHECK_FILES
IF %ERRORLEVEL% NEQ 0 (
    echo Faltan %ERRORLEVEL% archivos necesarios. Se cancela el procesamiento.
    GOTO :EOF
)
echo Se confirmó que todos los archivos existen. Se inicia el procesamiento.

GOTO :EOF

:CHECK_FILES
setlocal
set MISSING=0
for %%f in (config.ini data.csv template.xlsx) do (
    IF NOT EXIST "%%f" (
        echo Advertencia: no se encuentra %%f.
        set /a MISSING+=1
    )
)
endlocal & exit /b %MISSING%

En la última línea, %MISSING% se expande antes de que se ejecute endlocal, por lo que el valor de la variable de la subrutina se puede devolver como código de salida al código que la llamó.

Ejemplo de ejecución cuando no existe config.ini:

- □ ×
Í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>file-checker.cmd
Advertencia: no se encuentra config.ini.
Falta 1 archivo necesario. Se cancela el procesamiento.
C:\users\user>

Cuando existen todos los archivos:

- □ ×
Í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>file-checker.cmd
Se confirmó que todos los archivos existen. Se inicia el procesamiento.
C:\users\user>

Resumen

OperaciónNotación
Llamar a una subrutinaCALL :nombre_de_etiqueta argumento1 argumento2 ...
Finalizar una subrutinaEXIT /B código_de_salida
Hacer referencia a los argumentos%1, %~1 (sin comillas)
Devolver un númeroEXIT /B N → en el código que llama, consultar %ERRORLEVEL%
Devolver una cadenaEjecutar endlocal & set nombre_de_variable=valor en una sola línea
Evitar que la ejecución continúe en la subrutinaColocar GOTO :EOF al final del código principal

Artículos relacionados

Ejercicio

Problema de práctica

¿Cuál es la técnica que se usa para devolver una cadena como valor de retorno desde una subrutina?

回答がサーバーに送信されることはありません
#Archivos por lotes #Subrutinas #call #ERRORLEVEL #setlocal #Símbolo del sistema