HOWTO · Batch
Crear una función en Batch Script
Este tutorial discutirá cómo crear una función en Batch Script.
En esta página
Los archivos Batch no definen funciones mediante una palabra clave de declaración independiente. Una subrutina reutilizable es una etiqueta que se invoca con CALL; CALL ejecuta los comandos que siguen a esa etiqueta y vuelve al comando siguiente a la llamada. Estos ejemplos usan la sintaxis de Windows CMD y deben ejecutarse en Windows, desde un archivo .bat o .cmd.
Cómo funcionan las funciones de Batch
A una «función» de Batch se la suele llamar subrutina. Su etiqueta indica el punto de entrada, mientras que CALL :label transfiere el control a ella y conserva el punto al que debe volver. Una etiqueta por sí sola no crea un ámbito independiente ni retorna automáticamente. Usa EXIT /B dentro de la subrutina para volver a quien la llamó; sin un retorno explícito, la ejecución puede continuar por etiquetas y comandos posteriores. EXIT /B sale del archivo Batch actual cuando este no se está ejecutando como subrutina.
Definir y llamar a una función de Batch
Coloca la llamada antes de la etiqueta y termina el cuerpo principal con GOTO :EOF para evitar que la ejecución continúe dentro de la subrutina. En el script generado, la subrutina muestra un saludo y vuelve a quien la llamó.
Para ver un pequeño script de Windows CMD sin dar a entender que CMD se ejecutó aquí, ejecuta este script de Python. Imprime el código fuente de Batch; guarda esa salida en un archivo .bat o .cmd y ejecútalo en Windows CMD. El código y las etiquetas o textos de salida visibles en el ejemplo permanecen en inglés.
print('''@echo off
call :greet "Ada"
echo Back in the main script.
goto :eof
:greet
echo Hello, %~1!
exit /b 0''')
@echo off
call :greet "Ada"
echo Back in the main script.
goto :eof
:greet
echo Hello, %~1!
exit /b 0
El script generado está destinado a Windows CMD; Python imprime el código fuente, pero no lo ejecuta. GOTO :EOF termina el flujo principal y EXIT /B 0 devuelve un estado de éxito desde la etiqueta llamada. 0 es el código convencional de éxito; un código distinto de cero puede indicar un error a quien llamó a la subrutina.
Pasar argumentos a una función de Batch
Los argumentos se escriben después de la etiqueta en el comando CALL y se separan con espacios. Dentro de la subrutina, %1 es el primer argumento, %2 el segundo, y así sucesivamente. Conviene usar %~1 cuando se quiere obtener el primer argumento sin las comillas que lo rodeen; la tilde no hace que el valor sea seguro para insertarlo en cualquier comando, así que pon entre comillas los valores que uses como rutas o texto.
Este ejemplo de Python imprime un script de Batch completo que pasa un argumento con un espacio; guarda el código impreso en un archivo .bat o .cmd para ejecutarlo en Windows CMD. La subrutina :show lee el valor como %~1. El código y las etiquetas o textos de salida visibles en el ejemplo permanecen en inglés.
print("""@echo off
call :show "Ada Lovelace"
goto :eof
:show
echo Name: %~1
exit /b 0""")
@echo off
call :show "Ada Lovelace"
goto :eof
:show
echo Name: %~1
exit /b 0
Mantén la expansión de argumentos dentro de comparaciones entre comillas o asignaciones SET entre comillas cuando el valor pueda contener espacios o metacaracteres de comandos. El análisis de Batch tiene varias fases de expansión, por lo que valores complejos como %, & y | requieren especial cuidado.
Valores de retorno y códigos de salida
Batch no tiene un mecanismo integrado para devolver un valor de función. Un patrón habitual consiste en guardar el resultado en una variable de entorno y usar por separado el código de salida de la subrutina para indicar éxito o error. Este ejemplo de Python imprime un script de Batch completo que llama a una subrutina con dos argumentos, comprueba su estado inmediatamente después de CALL y, si hay éxito, lee la variable del resultado. Guarda el código impreso en un archivo .bat o .cmd para ejecutarlo en Windows CMD. El código y las etiquetas o textos de salida visibles en el ejemplo permanecen en inglés.
print("""@echo off
setlocal EnableExtensions
call :add 5 10
if errorlevel 1 goto add_failed
echo Sum: %sum%
goto :eof
:add_failed
echo Addition failed.
goto :eof
:add
if "%~1"=="" exit /b 1
if "%~2"=="" exit /b 1
setlocal
set /a "_sum=%~1 + %~2"
endlocal & set "sum=%_sum%"
exit /b 0""")
@echo off
setlocal EnableExtensions
call :add 5 10
if errorlevel 1 goto add_failed
echo Sum: %sum%
goto :eof
:add_failed
echo Addition failed.
goto :eof
:add
if "%~1"=="" exit /b 1
if "%~2"=="" exit /b 1
setlocal
set /a "_sum=%~1 + %~2"
endlocal & set "sum=%_sum%"
exit /b 0
La etiqueta lee los valores posicionales como %~1 y %~2. SETLOCAL mantiene local la variable temporal _sum; en la misma línea de comandos, CMD expande %_sum% antes de ejecutar ENDLOCAL y después asigna ese valor a la variable sum de quien llamó a la subrutina. Mantén ENDLOCAL & SET en una sola línea. Este ejemplo espera argumentos enteros: si falta alguno, devuelve el estado 1; si la suma se completa, devuelve el estado 0.
Manejar errores en una función de Batch
Valida las entradas necesarias al principio de la subrutina y devuelve un estado distinto de cero si falta alguna. Este ejemplo de Python imprime un script de Batch completo que llama a la misma etiqueta de validación primero sin una entrada necesaria y luego con ella; cada comprobación if errorlevel 1 va inmediatamente después de su CALL. Guarda el código impreso en un archivo .bat o .cmd para ejecutarlo en Windows CMD. El código y las etiquetas o textos de salida visibles en el ejemplo permanecen en inglés.
print("""@echo off
call :require_value
if errorlevel 1 (
echo Missing input: rejected with status 1.
) else (
echo Missing input: accepted.
)
call :require_value "report.txt"
if errorlevel 1 (
echo Valid input: rejected.
) else (
echo Valid input: accepted with status 0.
)
goto :eof
:require_value
if "%~1"=="" exit /b 1
exit /b 0""")
@echo off
call :require_value
if errorlevel 1 (
echo Missing input: rejected with status 1.
) else (
echo Missing input: accepted.
)
call :require_value "report.txt"
if errorlevel 1 (
echo Valid input: rejected.
) else (
echo Valid input: accepted with status 0.
)
goto :eof
:require_value
if "%~1"=="" exit /b 1
exit /b 0
La primera llamada llega a la rama de error porque falta el valor requerido; la segunda llega a la rama de éxito. if errorlevel 1 significa que el nivel de error actual es igual o superior a 1; si importa el código exacto, comprueba los códigos más altos primero. Con un argumento válido, la subrutina puede continuar con su tarea y terminar con EXIT /B 0.
Usa EXIT /B en lugar de EXIT para volver desde una subrutina: EXIT cierra la sesión de CMD, mientras que EXIT /B vuelve desde el contexto Batch actual. Si un CALL apunta a una etiqueta inexistente, CMD informa de un error; escribir las etiquetas de manera coherente y mantener claramente emparejadas las llamadas con sus etiquetas facilita el diagnóstico. Los ejemplos de Python imprimen código fuente de Batch; no lo ejecutan. Para observar su comportamiento en Batch, ejecuta los scripts guardados en Windows CMD.