0

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
FreeSoftwareServers
  • 2,271
  • 1
  • 33
  • 57
  • I am struggling to understand where `FILEPATH..` fits in, can you please elaborate. – Gerhard Aug 20 '20 at 06:32
  • @Gerhard I added the MVCE, sorry.. – FreeSoftwareServers Aug 20 '20 at 06:55
  • It's the wildcard `*` in `tes*.txt` that causes the problem because the `for` loop tries to resolve it… – aschipfl Aug 20 '20 at 06:59
  • @aschipfl thats what I am trying to resolve, yes. – FreeSoftwareServers Aug 20 '20 at 07:00
  • So technically, `filepath` would be a variable with a path to a file. If you set it like you are now using `*`, then it actually does not make sense to be named a path to a file. What is your intended usage for `filepath`, other than just `echo`ing it, then I can give you a solution. – Gerhard Aug 20 '20 at 07:03
  • There is a reason I broke it down to be simple, the goal is to set `"FILEPATH=C:\tmp\test *.txt"` as the variable in the `script.cmd` then I can do my `building in Wildcard checking` – FreeSoftwareServers Aug 20 '20 at 07:06

2 Answers2

1

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
)
Gerhard
  • 22,678
  • 7
  • 27
  • 43
0

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 . . .
FreeSoftwareServers
  • 2,271
  • 1
  • 33
  • 57