Usar parámetros en archivos por lotes en la línea de comandos de Windows

161

En Windows, ¿cómo accede a los argumentos pasados ​​cuando se ejecuta un archivo por lotes?

Por ejemplo, digamos que tengo un programa llamado hello.bat. Cuando entro hello -aen una línea de comandos de Windows, ¿cómo hago para que mi programa sepa que -ase pasó como argumento?

Una persona
fuente
Cómo pasar parámetros de línea de comandos a un archivo por lotes: stackoverflow.com/questions/26551/…
Eric Leschinski
3
Menciona "línea de comando DOS".
David R Tribble

Respuestas:

287

Como ya han dicho otros, se puede acceder a los parámetros pasados ​​a través de la línea de comandos en archivos por lotes con la notación %1a %9. También hay otros dos tokens que puedes usar:

  • %0es el nombre del ejecutable (archivo por lotes) como se especifica en la línea de comando .
  • %*son todos los parámetros especificados en la línea de comando ; esto es muy útil si desea reenviar los parámetros a otro programa.

También hay muchas técnicas importantes a tener en cuenta además de simplemente cómo acceder a los parámetros.

Comprobando si se pasó un parámetro

Esto se hace con construcciones como IF "%~1"=="", lo cual es cierto si y solo si no se pasó ningún argumento. Tenga en cuenta el carácter tilde que hace que las comillas circundantes se eliminen del valor de %1; sin tilde obtendrá resultados inesperados si ese valor incluye comillas dobles, incluida la posibilidad de errores de sintaxis.

Manejar más de 9 argumentos (o simplemente hacer la vida más fácil)

Si necesita acceder a más de 9 argumentos, debe usar el comando SHIFT. Este comando cambia los valores de todos los argumentos en un lugar, de modo que %0toma el valor de %1, %1toma el valor de %2, etc. %9toma el valor del décimo argumento (si está presente), que no estaba disponible a través de ninguna variable antes de llamar SHIFT(enter comando SHIFT /?para más opciones).

SHIFTTambién es útil cuando desea procesar fácilmente los parámetros sin requerir que se presenten en un orden específico. Por ejemplo, un script puede reconocer las banderas -ay -ben cualquier orden. Una buena manera de analizar la línea de comando en tales casos es

:parse
IF "%~1"=="" GOTO endparse
IF "%~1"=="-a" REM do something
IF "%~1"=="-b" REM do something else
SHIFT
GOTO parse
:endparse
REM ready for action!

Este esquema le permite analizar líneas de comando bastante complejas sin volverse loco.

Sustitución de parámetros por lotes

Para los parámetros que representan nombres de archivo, el shell proporciona muchas funciones relacionadas con el trabajo con archivos a los que no se puede acceder de ninguna otra manera. Se accede a esta funcionalidad con construcciones que comienzan con %~.

Por ejemplo, para obtener el tamaño del archivo pasado como argumento, use

ECHO %~z1

Para obtener la ruta del directorio desde el que se inició el archivo por lotes (¡muy útil!) Puede usar

ECHO %~dp0

Puede ver el rango completo de estas capacidades escribiendo CALL /?en el símbolo del sistema.

Jon
fuente
44
La construcción: parse,: endparse es belleza, incluso con GOTO. ¡Gracias! (Quiero decir, el DOS-BASIC forzó GOTO)
mmrtnt
1
Esta técnica puede fallar al llamar a BAT desde powershell. Un argumento citado como se "name=John"hará name Johndurante exe. Una solución alternativa es rodear con comillas simples,'"name=John"'
cmcginty
1
¿Cómo he pasado tanto tiempo sin CALL /?? Aquí he estado dando vueltas con Google todo el tiempo.
bigtlb
@ Jon escribí el archivo bat que contiene un solo código echo% 1 si lo llamo a través de cmd, por ejemplo, xx.bat & parameter> "C: \ yy.txt" llamando al archivo bat con parámetro y escribiendo en el archivo txt pero si doy & en el parámetro al principio o al final no funciona. Cualquier otro texto que funcione bien.
Alex Mathew
56

Uso de parámetros en archivos por lotes:% 0 y% 9

Los archivos por lotes pueden referirse a las palabras pasadas como parámetros con los tokens: %0to %9.

%0 is the program name as it was called.
%1 is the first command line parameter
%2 is the second command line parameter
and so on till %9.

Los parámetros pasados ​​en la línea de comandos deben ser caracteres alfanuméricos y delimitados por espacios. Dado que %0es el nombre del programa como se llamó, en DOS %0estará vacío para AUTOEXEC.BAT si se inicia en el momento del arranque.

Ejemplo:

Ponga el siguiente comando en un archivo por lotes llamado mybatch.bat:

@echo off
@echo hello %1 %2
pause

Invocar el archivo por lotes de esta manera: mybatch john billygeneraría:

hello john billy

Obtenga más de 9 parámetros para un archivo por lotes, use:% *

La ficha de porcentaje de estrella %*significa "el resto de los parámetros". Puede usar un bucle for para capturarlos, como se define aquí:

http://www.robvanderwoude.com/parameters.php

Notas sobre delimitadores para parámetros de lote

Los archivos por lotes ignoran algunos caracteres en los parámetros de la línea de comandos, dependiendo de la versión de DOS, si están "escapados" o no, y a menudo según su ubicación en la línea de comandos:

commas (",") are replaced by spaces, unless they are part of a string in 
double quotes

semicolons (";") are replaced by spaces, unless they are part of a string in 
double quotes

"=" characters are sometimes replaced by spaces, not if they are part of a 
string in double quotes

the first forward slash ("/") is replaced by a space only if it immediately 
follows the command, without a leading space

multiple spaces are replaced by a single space, unless they are part of a 
string in double quotes

tabs are replaced by a single space

leading spaces before the first command line argument are ignored
Eric Leschinski
fuente
5

Los archivos por lotes pasan automáticamente el texto después del programa siempre que sean variables a las que asignarlos. Se pasan en orden para ser enviados; Por ejemplo,% 1 será la primera cadena enviada después de llamar al programa, etc.

Si tienes Hello.bat y los contenidos son:

@echo off
echo.Hello, %1 thanks for running this batch file (%2)
pause

e invocas el lote al mando a través de

hola.bat APerson241% fecha%

deberías recibir este mensaje:

Hola, APerson241, gracias por ejecutar este archivo por lotes (11/01/2013)

rud3y
fuente
4

@ Jon's :parse/ :endparseesquema es un gran comienzo, y tiene mi gratitud por la aprobación inicial, pero si crees que el tortuoso sistema por lotes de Windows te dejaría así de fácil ... bueno, amigo mío, te sorprenderás. He pasado todo el día con este demonio, y después de mucha investigación y experimentación dolorosa finalmente logré algo viable para una utilidad de la vida real.

Digamos que queremos implementar una utilidad foobar. Requiere un comando inicial. Tiene un parámetro opcional --fooque toma un valor opcional (que no puede ser otro parámetro, por supuesto); si falta el valor, su valor predeterminado es default. También tiene un parámetro opcional --barque toma un valor requerido . Por último, puede tomar una bandera --bazsin valor permitido. Ah, y estos parámetros pueden venir en cualquier orden.

En otras palabras, se ve así:

foobar <command> [--foo [<fooval>]] [--bar <barval>] [--baz]

¿Complicado? No, eso parece bastante típico de las utilidades de la vida real. ( gitalguien?)

Sin más preámbulos, aquí hay una solución:

@ECHO OFF
SETLOCAL
REM FooBar parameter demo
REM By Garret Wilson

SET CMD=%~1

IF "%CMD%" == "" (
  GOTO usage
)
SET FOO=
SET DEFAULT_FOO=default
SET BAR=
SET BAZ=

SHIFT
:args
SET PARAM=%~1
SET ARG=%~2
IF "%PARAM%" == "--foo" (
  SHIFT
  IF NOT "%ARG%" == "" (
    IF NOT "%ARG:~0,2%" == "--" (
      SET FOO=%ARG%
      SHIFT
    ) ELSE (
      SET FOO=%DEFAULT_FOO%
    )
  ) ELSE (
    SET FOO=%DEFAULT_FOO%
  )
) ELSE IF "%PARAM%" == "--bar" (
  SHIFT
  IF NOT "%ARG%" == "" (
    SET BAR=%ARG%
    SHIFT
  ) ELSE (
    ECHO Missing bar value. 1>&2
    ECHO:
    GOTO usage
  )
) ELSE IF "%PARAM%" == "--baz" (
  SHIFT
  SET BAZ=true
) ELSE IF "%PARAM%" == "" (
  GOTO endargs
) ELSE (
  ECHO Unrecognized option %1. 1>&2
  ECHO:
  GOTO usage
)
GOTO args
:endargs

ECHO Command: %CMD%
IF NOT "%FOO%" == "" (
  ECHO Foo: %FOO%
)
IF NOT "%BAR%" == "" (
  ECHO Bar: %BAR%
)
IF "%BAZ%" == "true" (
  ECHO Baz
)

REM TODO do something with FOO, BAR, and/or BAZ
GOTO :eof

:usage
ECHO FooBar
ECHO Usage: foobar ^<command^> [--foo [^<fooval^>]] [--bar ^<barval^>] [--baz]
EXIT /B 1

Sí, realmente es tan malo. Vea mi publicación similar en https://stackoverflow.com/a/50653047/421049 , donde proporciono más análisis de lo que está sucediendo en la lógica y por qué usé ciertas construcciones.

Horrible. La mayor parte de eso tuve que aprender hoy. Y duele.

Garret Wilson
fuente
3

Utilice variables, es decir, las .BATvariables y llame %0a%9

Tohava
fuente