Pasar parámetros con nombre a un script por lotes con caracteres especiales

Aug 20 2020

Encontré y modifiqué un fragmento de código para permitir pasar parámetros con nombre ilimitados a un script por lotes.

Accediendo a un número desconocido de comandos (parámetros) en un archivo por lotes

Todo funcionaba muy bien, pero ahora estoy construyendo un comodín comprobando el script y descubrí que si paso un valor como este "FILEPATH=C:\tmp\test *.txt"que FILEPATHno está definido por mi fragmento de código. Como no lo creé realmente, en parte desconozco cómo funciona y podría modificarse para permitir caracteres especiales.

Aquí está el fragmento de código para permitir parámetros con nombre que me gustaría recibir orientación sobre cómo modificar:

::Set Named Arguments
set argCount=0
for %%x in (%*) do (
   set /A argCount+=1
   set "argVec[!argCount!]=%%~x"
   set %%x
)

Actualizar:

Cambié el bucle for a for /F delims^=^"^ tokens^=* %%x in (%*) do (y ahora definirá FILEPATH con un WILDCARD, pero elimina el primero "y luego convierte todos los argumentos en una línea y también elimina el final ". ¿Quizás necesito una forma de usar el argcountpara correlacionar la posición alfanumérica de la set %%xlínea?

Otro pensamiento, dado que el cambio anterior al bucle for acepta el comodín, pero crea una única variable larga que contiene todos los parámetros pasados script.cmd, tal vez pueda recorrerla (la variable larga) nuevamente y dividir los argumentos nombrados.

Actualizar:

Uso de ejemplo:

script.cmd:

@ECHO OFF
CLS
::Set Named Arguments
set argCount=0
for %%x in (%*) do (
   set /A argCount+=1
   set "argVec[!argCount!]=%%~x"
   set %%x
)
ECHO %FILEPATH%
ECHO %VAR%
EXIT /B

test.cmd:

@ECHO OFF
CLS

::Doesn't Work
CALL "C:\tmp\script.cmd" "FILEPATH=C:\tmp\tes*.txt" "VAR=2"
PAUSE
::Works Fine
CALL "C:\tmp\script.cmd" "FILEPATH=C:\tmp\test.txt" 
PAUSE

Respuestas

1 Gerhard Aug 20 2020 at 07:25

Usando su método actual definiéndolo FILEPATH=como un parámetro.

Nota: Necesito expresar que esto es una tendencia un poco peligrosa. La razón es que, si alguna de las variables de entrada contiene algo similar PATH=Somepath, se romperá el entorno inmediato mientras se ejecuta el script. Así que asegúrese de verificar los tipos de entrada que se pasarán.

@echo off & setlocal enabledelayedexpansion
(set "%~1" & set "%~2" & set "%~3" & set "%~4")>nul
set argCount=0
if defined FILEPATH (
  for %%x in ("%FILEPATH%") do (
     set /A argCount+=1
     set "argVec[!argCount!]=%%~x"
     echo argVec[!argCount!]
 )
 echo %FILEPATH%
) else (
 echo FILEPATH not defined
)
FreeSoftwareServers Aug 20 2020 at 16:34

Mi solución completa basada en la increíble respuesta de @ Gerhard. Esto todavía me permite tomar una cantidad ilimitada de variables ingresadas en un orden desconocido en "VALUE=KEY"formato, y no conocer el FILEPATHargumento posicional, pero como el lote tiene limitaciones para usar solo %1-->%9, sentí que era más fácil / mejor manejar / permitir que FILEPATHsea ​​cualquiera de los primeros 9 PARAMS. Esto realmente me enseñó sobre las cosas que das por sentado en shells como BASH y también, lo que BASH está haciendo "detrás de escena". La idea era construir una búsqueda con comodines, ya que my script.cmdsiempre será llamado por un "script principal" con params y quiero que sea similar a BASH(permitir que los usuarios finales usen comodines).

script.cmd:

@ECHO OFF
CLS
::SET Named Arguments
SET argCount=0
for %%x in (%*) do (
   SET /A argCount+=1
   SET "argVec[!argCount!]=%%~x"
   SET %%x
)

::Wildcards in FilePath?
(SET "%~1" & SET "%~2" & SET "%~3" & SET "%~4" & SET "%~5" & SET "%~6" & SET "%~7" & SET "%~8" & SET "%~9")>nul
SET argCount=0
IF DEFINED FILEPATH (
  FOR %%x IN ("%FILEPATH%") DO (
     SET /A argCount+=1
     SET "argVec[!argCount!]=%%~x"
 )
 CALL :FindFileWildCard "%FILEPATH%" FILEPATH
) ELSE (
   ECHO No "FILEPATH=C:\path\print.doc" Defined!
   PAUSE
   GOTO:EOF
)

ECHO %FILEPATH%
ECHO %VAR%
ECHO %VAR2%
ECHO %VAR3%
ECHO %VAR4%
ECHO %VAR5%
ECHO %VAR6%
ECHO %VAR7%
ECHO %VAR8%
ECHO %VAR9%
ECHO %VAR10%
GOTO :EOF

::Functions
:FindFileWildCard
::Does Path contain WildCards?
ECHO "%~1" | FIND /i "*" >nul
IF %ERRORLEVEL% EQU 0 (
 FOR /F "Tokens=*" %%F IN ('DIR /B /S "%~1"') DO (
 SET %2=%%F
 EXIT /B
 )
)
ECHO "%~1" | FIND /i "?" >nul
IF %ERRORLEVEL% EQU 0 (
 FOR /F "Tokens=*" %%F IN ('DIR /B /S "%~1"') DO (
 SET %2=%%F
 EXIT /B
 )
)
EXIT /B

:EOF

test.cmd:

@ECHO OFF
CLS

CALL "C:\tmp\script.cmd" "VAR=VAR" "VAR2=VAR2" "VAR3=VAR3" "FILEPATH=C:\tmp\tmp space\te*.txt"  "VAR4=VAR4" "VAR5=VAR5" "VAR6=VAR6" "VAR7=VAR7" "VAR8=VAR8" "VAR9=VAR9" "VAR10=VAR10"
PAUSE
CALL "C:\tmp\script.cmd" "VAR=VAR" "VAR2=VAR2" "VAR3=VAR3" "FILEPATH=C:\tmp\tmp space\test with spa?*.txt"  "VAR4=VAR4" "VAR5=VAR5" "VAR6=VAR6" "VAR7=VAR7" "VAR8=VAR8" "VAR9=VAR9" "VAR10=VAR10"
PAUSE
CALL "C:\tmp\script.cmd" "VAR=VAR" "VAR2=VAR2" "VAR3=VAR3" "FILEPATH=C:\tmp\test.txt"  "VAR4=VAR4" "VAR5=VAR5" "VAR6=VAR6" "VAR7=VAR7" "VAR8=VAR8" "VAR9=VAR9" "VAR10=VAR10"
PAUSE

Resultado:

C:\tmp\tmp space\test with space.txt
VAR
VAR2
VAR3
VAR4
VAR5
VAR6
VAR7
VAR8
VAR9
VAR10
Press any key to continue . . .