FreeSoftwareServers
FreeSoftwareServers

Reputation: 2831

Pass Named Parameters to Batch Script with Special Characters

I found and modified a code snippet to allow passing unlimited named parameters to a batch script.

Accessing unknown number of commands (parameters) in batch file

Everything was working great, but now I'm building in Wildcard checking into the script and I found if I pass a value like this "FILEPATH=C:\tmp\test *.txt" that FILEPATH doesn't get defined by my code snippet. As I didn't truly create it I am partly unaware of how it works and could be modified to allow special characters.

Here is the code snippet to allow named params that I'd like guidance on modifiying:

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

Update:

I changed the for loop to for /F delims^=^"^ tokens^=* %%x in (%*) do ( and it will now define the FILEPATH with a WILDCARD, but it strips the first " and then makes all the arguments into one line and also strips the final ". Perhaps I need a way to use the argcount to correlate the alphanumeric position of the set %%x line?

Another thought, since the above change to the for loop does accept the wildcard, but creates a single long variable containing all params passed to script.cmd, perhaps I can loop over it (the long variable) again and split up the named arguments.

Update:

Example usage:

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

Upvotes: 0

Views: 319

Answers (2)

user7818749
user7818749

Reputation:

Using your current method by defining FILEPATH= as a parameter.

Note: I need to express that this is trending a little on the dangerous side. Reason being, if any of the input variables contains something like PATH=Somepath it will break the immediate environment while the script is running. So ensure you check the input types that will be passed.

@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
)

Upvotes: 1

FreeSoftwareServers
FreeSoftwareServers

Reputation: 2831

My full solution based on @Gerhard's awesome answer. This still allows me to take an unlimited amount of variables input in unknown order in "VALUE=KEY" format, and not know the FILEPATH positional argument, but as batch has limitations on using only %1-->%9 I felt it easiest/best to handle/allow that FILEPATH be any of the first 9 PARAMS. This really taught me about the things you take for granted in shells like BASH and also, what BASH is doing "behind the scenes". The idea was to build in wildcard searching as my script.cmd will always be called by a "parent script" w/ params and I want it to be similar to BASH (allow end users to use wildcards).

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

Result:

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

Upvotes: 0

Related Questions