Есть ли способ передать параметры "по имени" (а не по заказу) в пакетный .bat файл?
Мне нужно иметь возможность передавать параметры в пакетный файл Windows BY NAME (и НЕ по заказу). Моя цель здесь - предоставить конечному пользователю гибкость для передачи параметров в любом порядке, и пакетный файл все равно сможет обрабатывать их.
Пример, чтобы сделать мой вопрос более ясным:
в командной строке пользователь выполняет следующие действия:
somebatchfile.bat originalFile.txt newFile.txt
Внутри somebatchfile.bat
имеется простой оператор для копирования содержимого исходного файла (первый параметр% 1%) в новый файл (второй параметр% 2%). Это может быть так просто, как следующее утверждение:
copy %1% %2%
Теперь, если пользователь передает вышеуказанные параметры в обратном порядке, результат будет далек от желательности (на самом деле это очень НЕПРАВИЛЬНО).
Итак, есть ли способ для пользователя передать параметры по имени: например. somebatchfile.bat "SOURC=originalFile.txt" "TARGET=newFile.txt"
и script, чтобы распознать их и использовать в правильных местах, например. copy %SOURCE% %TARGET%
?
Спасибо,
Ответы
Ответ 1
Да, вы могли бы сделать что-то подобное, хотя я не думаю, что вы можете использовать "=" в качестве разделителя токенов. Вы можете использовать двоеточие ":", 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
[изменить]
Хорошо, может быть, это было слишком близко к постели для меня прошлой ночью, но, глядя снова утром, вы можете сделать это:
@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
, поэтому они устанавливаются как переменные среды. Тем не менее они должны указываться в командной строке.
Ответ 2
Немного поздно для вечеринки:) Это мое предложение для управления параметрами "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
Ответ 3
Другим способом, который мне очень понравился:
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
Ответ 4
Я хотел видеть возможность чтения именованного параметра, поставляемого в пакетную программу. Например:
myBatch.bat arg1 arg2
Показатель чтения может быть выполнен следующим образом:
%~1 would be arg1
%~2 would be arg2
Выше аргумент, предоставляемый пакетной программе, легко читается, но каждый раз, когда вы его выполняете, вы должны поддерживать порядок и помнить, что должен иметь аргумент arg1. Чтобы преодолеть это, параметр может быть предоставлен в виде ключа: формат значения. И команда будет выглядеть следующим образом:
mybatch.bar key1:value1 key2:value2
Хотя нет прямого пути для анализа такого списка аргументов. Я написал следующий цикл вложенных циклов в пакетном script, который будет в основном анализировать и создавать переменную среды с ключом как имя и присваиваемое ему значение1. Таким образом, вы можете прочитать все аргументы, предоставленные с использованием прямого способа чтения переменной среды среды.
@echo off
FOR %%A IN (%*) DO (
FOR /f "tokens=1,2 delims=:" %%G IN ("%%A") DO setLocal %%G=%%H
)
Затем вы можете использовать формат %key1%
, чтобы прочитать все предоставленные аргументы.
НТН
Ответ 5
Очень старый вопрос, но я думаю, что нашел изящный способ (без внешних зависимостей) передачи аргументов 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
вместо пустого)
Наслаждаться.
Ответ 6
Я думаю, что вы ищете поддержку getopt в сценариях Windows, которые, к сожалению, не существуют полностью. Самое близкое, что вы, вероятно, можете получить, это использовать GetOpt.btm script. С помощью этого вы можете выполнить команду script с помощью команды:
somebatchfile.bat /SOURC:originalFile.txt /TARGET:newFile.txt
код:
@echo off
:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
:: GetOpt - Process command line options
::
:: Michael Fross
:: [email][email protected][/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 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_*
Ответ 7
:parse
IF "%~1"=="" GOTO endparse
ECHO "%~1"| FIND /I "=" && SET "%~1"
SHIFT /1
GOTO parse
:endparse
Этот код проверяет все параметры, разбивает все внешние кавычки и, если присутствует знак равенства, устанавливает переменную в значение.
на основе этого ответа: Использование параметров в пакетных файлах в командной строке DOS
Ответ 8
Возьми эту попытку (чистая партия):
set PARAM_0=0
:parameters_parse
set parameter=%~1
if "%parameter%"=="" goto parameters_parse_done
if "%parameter:~0,1%"=="-" (
set ARG_%parameter:~1%="%~2"
shift
shift
goto parameters_parse
)
if "%parameter:~0,1%"=="/" (
set ARG_%parameter:~1%="%~2"
shift
shift
goto parameters_parse
)
set /a PARAM_0=%PARAM_0%+1
set PARAM_%PARAM_0%="%~1"
shift
goto parameters_parse
:parameters_parse_done
rem Insert your script here
и некоторые тесты:
call args.bat /bar="Hello World" Test1 -baz "Test test test" /foo=Test1 Test2
echo foo=%ARG_foo%
echo bar=%ARG_bar%
echo baz=%ARG_baz%
echo count=%PARAM_0%
echo 1=%PARAM_1%
echo 2=%PARAM_2%
Выходы:
foo="Test1"
bar="Hello World"
baz="Test test test"
count=2
1="Test1"
2="Test2"