2011-03-07 30 views
27

我需要能夠傳遞參數到一個Windows批處理文件的名稱(而不是按順序)。我的目的是讓最終用戶能夠靈活地以任何順序傳遞參數,批處理文件仍應能夠處理它們。有沒有辦法將「按名稱」(而不是按順序)傳遞給批處理.bat文件?

一個例子,使我的問題更加清晰:

在命令行

,用戶執行以下操作: somebatchfile.bat originalFile.txt newFile.txt

裏面somebatchfile.bat有一個簡單的語句來複制原始文件的內容(第一個參數% 1%)添加到新文件(第二個參數%2%)。它可以是如下簡單: copy %1% %2%

現在,如果用戶以相反的順序傳遞上述參數,結果將遠遠不可取(事實上非常錯誤)。

那麼,有沒有一種方法讓用戶按名稱傳遞參數:例如, somebatchfile.bat "SOURC=originalFile.txt" "TARGET=newFile.txt",腳本可以在正確的位置識別它們並使用他們,例如copy %SOURCE% %TARGET%

感謝,

+0

這個問題是這樣的:[指定命令行參數像shell腳本的名稱=值對](http://stackoverflow.com/a/43008569/3957754)希望這有助於。 – JRichardsz 2017-03-24 20:33:37

+0

但OP的問題是關於_batch_(windows/dos),與_bash_完全不同。 – 2017-11-07 23:31:54

回答

16

是的,你可以做這樣的事情,雖然我不認爲你可以使用「=」作爲標記分隔符。你可以使用冒號「:」,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這些確實會設置環境變量之前評估。但是它們必須在命令行上引用必須

+0

感謝Dave,但是你的解決方案在批處理文件中涉及到「相當多的處理」。但是,最好的是一種「內置」功能類,它可以通過傳遞參數自動填充內部變量(在用戶腳本中)。例如:按照慣例,他們知道如果他們傳遞這樣的參數:「SOURC:originalFile.txt」,那麼他們的內部變量%name%和%val%將自動獲得正確的值。 – Pouya 2011-03-07 05:58:15

+3

@Pouya:這個**批處理腳本**只用一行代碼解析'name&value'對。這怎麼可能*相當多的處理*?但是,我發現你正在談論的是內置的功能 - 不,批處理腳本是一個非常有限的工具,微軟通過引入PowerShell(再次)間接地承認它。 – 2011-03-07 08:22:58

+0

Andriy,問題是:在我們的例子中,所有的批處理文件都是由最終用戶提供的,通常情況下,您不希望最終用戶在他們現有的腳本中添加一行代碼,只是爲了make'em兼容與您的解決方案。 – Pouya 2011-03-07 10:38:10

2

我認爲你正在尋找Windows批處理腳本中的getopt類型的支持,但不幸的是它不存在整體。您可能最接近的是使用GetOpt.btm 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'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_* 
4

我想看到的閱讀提供給批處理程序的命名參數的可能性。例如:

myBatch.bat arg1 arg2 

讀取參數如下進行:

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

以上提供給批處理程序的說法是容易閱讀,但隨後每次執行它,你要維持秩序,並記arg1應該有什麼。爲了克服它,參數可以作爲key:value格式提供。和命令如下所示:

mybatch.bar key1:value1 key2:value2 

雖然沒有直接的方法來解析這樣的參數列表。我在批處理腳本中編寫了以下嵌套for循環,它將基本上解析並創建環境變量,其中key1作爲名稱,並將value1分配給它。通過這種方式,您可以閱讀使用直接讀取環境變量的方式提供的所有參數。

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

之後,您可以使用%key1%格式來讀取所提供的所有參數。

HTH

+0

'setLocal'對我來說不起作用,但是'set'做到了。 – 2014-12-19 15:29:42

+0

setLocal通常在批處理程序範圍內工作,我不確定你試圖設置這些範圍的範圍。我更喜歡本地範圍,因爲這些參數將在批處理範圍內(並且應該)使用。 你是怎麼看它的?試圖讀取這些參數之前是否有EndLocal? – 2014-12-22 18:36:48

+0

我使用[IzPack的可執行文件](http://izpack.org/documentation/installation-files.html#executable-mark-file-executable-or-execute-it)標記將參數傳遞給我的腳本。我只是將這些參數寫入文件:'echo INSTALL_PATH:%INSTALL_PATH%>> text.txt'。 – 2014-12-22 19:48:06

4

其他辦法,我挺喜歡:

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 
+0

它不適用於包含空格的參數,如何改進以支持這種情況? – m0dest0 2017-08-18 04:16:48

0
:parse 
IF "%~1"=="" GOTO endparse 
ECHO "%~1"| FIND /I "=" && SET "%~1" 
SHIFT /1 
GOTO parse 
:endparse 

此代碼檢查所有參數,去除所有外部引號,並且如果等號存在,則將變量設置爲值。

基於這樣的回答:Using parameters in batch files at DOS command line

0

有點遲到了:)這是我管理「POSIX像」選項的建議。 例如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 
相關問題