Есть ли способ передать параметры "по имени" (а не по порядку) в пакетный файл .bat? - PullRequest
35 голосов
/ 07 марта 2011

Мне нужно иметь возможность передавать параметры в пакетный файл Windows ПО ИМЕНЕ (а НЕ по порядку). Моя цель здесь - предоставить конечному пользователю гибкость для передачи параметров в любом порядке, и пакетный файл все еще должен их обрабатывать.

Пример, поясняющий мой вопрос:

в командной строке пользователь делает следующее: somebatchfile.bat originalFile.txt newFile.txt

Внутри somebatchfile.bat есть простая инструкция для копирования содержимого исходного файла (первый параметр% 1%) в новый файл (второй параметр% 2%). Это может быть так просто, как следующее утверждение: copy %1% %2%

Теперь, если пользователь передает вышеуказанные параметры в обратном порядке, результат будет далек от желаемого (на самом деле очень НЕПРАВИЛЬНО).

Итак, есть ли способ для пользователя передать параметры по имени: например, somebatchfile.bat "SOURC=originalFile.txt" "TARGET=newFile.txt" и для сценария, чтобы распознать их и использовать их в правильных местах, например. copy %SOURCE% %TARGET%

Спасибо

Ответы [ 7 ]

23 голосов
/ 07 марта 2011

Да, вы можете сделать что-то подобное, хотя я не думаю, что вы можете использовать "=" в качестве разделителя токенов.Вы можете использовать, скажем, двоеточие ":", somebatchfile.bat "SOURC:originalFile.txt" "TARGET:newFile.txt".Вот пример того, как вы могли бы разделить токены:

@echo off

set foo=%1
echo input: %foo%

for /f "tokens=1,2 delims=:" %%a in ("%foo%") do set name=%%a & set val=%%b

echo name:  %name%
echo value: %val%

Запуск этого приведет к следующему:

C:\>test.bat SOURC:originalFile.txt
input: SOURC:originalFile.txt
name:  SOURC
value: originalFile.txt

[Edit]

Хорошо, возможнопрошлым вечером я был слишком близко ко сну, но сегодня утром снова посмотрев, вы можете сделать следующее:

@echo off

set %1
set %2

echo source: %SOURCE%
echo target: %TARGET%

Что может привести к этому (обратите внимание, что я изменил источник и цель в командной строке, чтобы показатьустановить и получить правильно):

C:\>test.bat "TARGET=newFile.txt" "SOURCE=originalFile.txt"
source: originalFile.txt
target: newFile.txt

Обратите внимание, что% 1 и% 2 оцениваются до set, поэтому они устанавливаются как переменные среды.Они должны однако указываться в командной строке.

8 голосов
/ 08 ноября 2017

Немного опоздал на вечеринку :) Это мое предложение по управлению опциями "posix like". Например mybatchscript.bat -foo=foovalue -bar=barvalue -flag

:parseArgs
:: asks for the -foo argument and store the value in the variable FOO
call:getArgWithValue "-foo" "FOO" "%~1" "%~2" && shift && shift && goto :parseArgs

:: asks for the -bar argument and store the value in the variable BAR
call:getArgWithValue "-bar" "BAR" "%~1" "%~2" && shift && shift && goto :parseArgs

:: asks for the -flag argument. If exist set the variable FLAG to "TRUE"
call:getArgFlag "-flag" "FLAG" "%~1" && shift && goto :parseArgs


:: your code here ...
echo FOO: %FOO%
echo BAR: %BAR%
echo FLAG: %FLAG%

goto:eof

.. и вот функции, которые делают работу. Вы должны поместить их в один пакетный файл

:: =====================================================================
:: This function sets a variable from a cli arg with value
:: 1 cli argument name
:: 2 variable name
:: 3 current Argument Name
:: 4 current Argument Value
:getArgWithValue
if "%~3"=="%~1" (
  if "%~4"=="" (
    REM unset the variable if value is not provided
    set "%~2="
    exit /B 1
  )
  set "%~2=%~4"
  exit /B 0
)
exit /B 1
goto:eof



:: =====================================================================
:: This function sets a variable to value "TRUE" from a cli "flag" argument
:: 1 cli argument name
:: 2 variable name
:: 3 current Argument Name
:getArgFlag
if "%~3"=="%~1" (
  set "%~2=TRUE"
  exit /B 0
)
exit /B 1
goto:eof

Сохраните файл как mybatchscript.bat и запустите

mybatchscript.bat -bar=barvalue -foo=foovalue -flag

Вы получите:

FOO: foovalue
BAR: barvalue
FLAG: TRUE
6 голосов
/ 18 августа 2015

Другой способ мне очень понравился:

set c=defaultC
set s=defaultS
set u=defaultU

:initial
if "%1"=="" goto done
echo              %1
set aux=%1
if "%aux:~0,1%"=="-" (
   set nome=%aux:~1,250%
) else (
   set "%nome%=%1"
   set nome=
)
shift
goto initial
:done

echo %c%
echo %s%
echo %u%

Запустите следующую команду:

arguments.bat -c users -u products

Будет генерировать следующий вывод:

users
defaultS
products
5 голосов
/ 05 ноября 2014

Я хотел увидеть возможность чтения именованного параметра, передаваемого в пакетную программу.Например:

myBatch.bat arg1  arg2 

Чтение параметра может быть выполнено следующим образом:

%~1 would be arg1
%~2 would be arg2

Приведенный выше аргумент, предоставленный пакетной программе, легко читается, но затем каждый раз, когда вы выполняете его, вы должныподдерживать порядок и помнить, что должен иметь arg1.Чтобы преодолеть это, параметр может быть предоставлен в формате ключ: значение.И команда будет выглядеть следующим образом:

mybatch.bar key1:value1 key2:value2

Хотя нет прямого способа проанализировать такой список аргументов.Я написал следующий вложенный цикл for в пакетном скрипте, который в основном будет анализировать и создавать переменную окружения с ключом1 в качестве имени и назначенным ему значением1.Таким образом, вы можете прочитать все предоставленные аргументы, используя прямой способ чтения переменных среды.

@echo off
FOR %%A IN (%*) DO (
   FOR /f "tokens=1,2 delims=:" %%G IN ("%%A") DO setLocal %%G=%%H
)

После этого вы можете использовать формат %key1% для чтения всех предоставленных аргументов.

HTH

3 голосов
/ 15 июля 2018

Очень старый вопрос, но я думаю, что нашел изящный способ (без внешних зависимостей) передачи key=value аргументов в командный файл.Вы можете протестировать метод с помощью следующего MWE:

@echo off
chcp 65001

rem name this file test.bat and call it with something like:
rem test keyc=foo keyd=bar whatever keya=123 keyf=zzz

setlocal enabledelayedexpansion

set "map=%*"
call :gettoken keya var1
call :gettoken keyb var2
call :gettoken keyc var3

rem replace the following block with your real batch
rem ************************************************
echo:
echo Map is "%map%"
echo Variable var1 is "%var1%"
echo Variable var2 is "%var2%"
echo Variable var3 is "%var3%"
echo:
echo Done.
echo:
pause
rem ************************************************

goto :eof
:gettoken
call set "tmpvar=%%map:*%1=%%"
if "%tmpvar%"=="%map%" (set "%~2=") else (
for /f "tokens=1 delims= " %%a in ("%tmpvar%") do set tmpvar=%%a
set "%~2=!tmpvar:~1!"
)
exit /b

Метод вполне:

  • гибкий, потому что key=value аргументы могут смешиваться с другими аргументами (такими как имена файлов), и потому что имя переменной, используемой для хранения значения, не зависит от имени ключа
  • масштабируемого, потому что легко добавить ключи
  • надежные, потому что все, что пропущено, что не разрешеноопределенные ключи игнорируются, а неназначенные ключи получают пустое значение (при желании вы можете легко изменить это поведение, чтобы они получили что-то вроде null или undefined вместо пустого)

Наслаждайтесь

2 голосов
/ 07 марта 2011

Я думаю, вы ищете поддержку getopt в пакетных скриптах Windows, которая, к сожалению, не существует полностью.Самое близкое, что вы можете получить, это использование скрипта GetOpt.btm .После этого вы можете выполнить свой скрипт, используя команду:

somebatchfile.bat /SOURC:originalFile.txt /TARGET:newFile.txt

Код:

@echo off
:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
:: GetOpt - Process command line options
:: 
:: Michael Fross
:: [email]michael@fross.org[/email]
:: [url]http://fross.org[/url]
::
:: This program scans the command line sent to it and sets various 
:: environment variables that coorespond to the settings.
::
:: It sets an OPTION_arg variable for each arg on the command line.
:: If a switch, the env var is set to 1.  If a value is given via the colon sign,
:: it's set to that value.  Note, there can not be any white space around the ':'
::
:: Use "If defined OPTION_arg" or "If %OPTION_arg eq value" to test for options
::
:: It also sets a parameter variable for each paramater entered: PARAM_1 to PARAM_n
:: PARAM_0 is a special value that contains the number of PARAMs.  Useful for looping
:: through all of them.  For example, do i = 1 to %PARAM_0 by 1 ...
::
:: In your batch file call getopt as:
::      call GetOpt.btm %$
::
:: I also recommend setting setlocal and endlocal in the host batch file so that
:: the option / param variable do not stick around after the host batch files exits.
::
:: Example usage:  BatchFile.btm /a /b:22 /longopt Parm1 Parm2 /quotedArg:"long quoted arg"
::   OPTION_a will equal 1.
::   OPTION_b will equal 22
::   OPTION_quotedArg will equal "long quoted arg"
::   OPTION_longopt will eqal 1.
::   PARAM_1 will equal Parm1
::   PARAM_2 will equal Parm2
::   PARAM_0 will be set to the number of parms, so 2 in this case
::
:: To get debug messages, set DEBUG=1.  This will give detailed information for each
:: parameter on the command line as getopt loops through the list.
::
:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::

:: Clean up the environment before we get going
unset getopt* OPTION_* PARAM_*
set getopt_ParmCounter=1

:: If in debug mode, kick off the display by showing the number of arguments
if defined DEBUG echo GetOpt is processing %# arguments:

:: Loop through all command line arguments one at a time.
for /L %i in (1,1,%#) do (
   if defined DEBUG (echo. %+ echo Scan #%i:)

   :: If first character starts with a - or / it must be an option
   iff %@instr[0,1,%[%i]] == - .or. %@instr[0,1,%[%i]] == / then
      set getopt_Parm=%[%i]
      if defined DEBUG echo  - Item "%getopt_Parm" is an option.

      :: Set the Equal Index to the position of the colon.  0 means none was found
      set getopt_EqIdx=%@index[%getopt_Parm,:]

      :: Display the index position of the colon
      if defined DEBUG .AND. %getopt_EqIdx GE 0 echo  - Found colon at index position "%getopt_EqIdx"

      :: If the index is GE 0 then we must have a colon in the option.
      :: set the OPTION value to the stuff to the right of the colon
      iff %getopt_EqIdx ge 0 then
         set getopt_ParmName=%@instr[2, %@Dec[%getopt_EqIdx] , %getopt_Parm]
         if defined DEBUG echo  - ParmName  = "%getopt_ParmName"
         set getopt_ParmValue=%@right[%@eval[-%getopt_EqIdx-1],%getopt_Parm]
         if defined DEBUG echo  - Parmvalue = "%getopt_ParmValue"
         set OPTION_%getopt_ParmName=%getopt_ParmValue
      else
         :: This is a flag, so simply set the value to 1
         if defined DEBUG echo  - No colon found in "%getopt_Parm"
         set getopt_ParmName=%@right[%@Dec[%@len[%getopt_Parm]],%getopt_Parm]
         set getopt_ParmValue=1
         if defined DEBUG echo  - ParmName = "%getopt_ParmName"
         set OPTION_%getopt_ParmName=%getopt_ParmValue
      endiff

      :: Regardless if there was a value or not, display what is going to occur
      if defined DEBUG echo  - Setting Variable OPTION_%getopt_ParmName=%getopt_ParmValue
   else
      :: There was no / or - found, therefore this must be a paramater, not an option
      if defined DEBUG echo  - "%[%i]" is a parameter, not an option
      set PARAM_%getopt_ParmCounter=%[%i]
      set PARAM_0=%getopt_ParmCounter
      if defined DEBUG echo  - Updating Number of Parms.  PARAM_0=%PARAM_0
      if defined DEBUG echo  - Setting Variable PARAM_%getopt_ParmCounter = %[%i]
      set getopt_ParmCounter=%@Inc[%getopt_ParmCounter]
   endiff
)

:: Display additional information
iff defined DEBUG then
   echo.
   echo There were %PARAM_0 parameters found.  Setting PARAM_0=%PARAM_0
   echo.
   echo GetOpt has completed processing %# arguments.  Ending Execution.
endiff

:: Perform cleanup
unset getopt_*
0 голосов
/ 07 июля 2016
:parse
IF "%~1"=="" GOTO endparse
ECHO "%~1"| FIND /I "=" && SET "%~1"
SHIFT /1
GOTO parse
:endparse

Этот код проверяет все параметры, удаляет все внешние кавычки и, если присутствует знак равенства, устанавливает значение переменной.

на основе этого ответа: Использование параметров в пакетных файлахв командной строке DOS

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...