Windowsバッチスクリプト(.bat)で渡された引数のリストを取得する


405

$@スクリプトに渡されたすべての引数のリストを保持するBashに対応するWindowsバッチ版を見つけたいのですが。

または私は気にする必要がありshiftますか?

回答:


622

dancavallaro%*、すべてのコマンドラインパラメーター(スクリプト名自体を除く)について、それを正しく持っています。また、次のものが役立つ場合もあります。

%0-バッチファイルを呼び出すために使用されるコマンドは、(可能性がありfoo..\fooc:\bats\foo.batなど、)
%1、最初のコマンドラインパラメータである
%22番目のコマンドラインパラメータである、
というようにまで%9(とSHIFT9日後にそれらのために使用することができます)。

%~nx0-呼び出し方法に関係なく、バッチファイルの実際の名前(some-batch.bat)
%~dp0-スクリプトへのドライブとパス(d:\ scripts)
%~dpnx0- スクリプトの完全修飾パス名(d:\ scripts \ some -batch.bat)

https://www.ss64.com/nt/syntax-args.htmlおよびhttps://www.robvanderwoude.com/parameters.htmlの詳細情報の例


11
SHIFTは%*に影響しないため、n番目のパラメーターからコマンドライン全体にアクセスするなど、直感的にSHIFT [/ n]を使用できないことに注意してください。
ヴァンジョーン2013年

4
私が発見した他の何かは%~dpn0、スクリプトへのドライブとパス、およびバッチファイルの名前を返しますが、拡張子は返しません。これ.ps1は、同じ名前のファイルを呼び出すバッチスクリプトを作成するときに特に便利です。基本的に、dはドライブをp指し、パスをn指し、ファイルの名前をx指し、拡張子を指します。その情報があれば、かなりのことができます。
Dan Atkinson

好奇心から、ECHOを使用してファイルのパスを出力したいが、拡張子を置き換えたい場合、どうすればよいでしょうか。
Matheus Rocha

2
@MatheusRocha@echo %~n0.my_ext
マットウィルキー

@mattwilkieありがとうございます。結果として何が印刷されるかを確認するために、ECHOを使用してそれを理解しました。
Matheus Rocha

149

%* スクリプトに渡されたすべての引数を保持しているようです。


なぜそれがそのようないくつかの文字を処理しないの&ですか?選択した複数のファイルの複数のパスを取得しようとすると([送信]メニューと "%*"を使用して、引数を.pyに渡す)、&caractersでリストが停止します。たとえば、2番目のファイルの&名前にa が含まれている場合、名前のの後の部分は&スキップされ、残りのファイルもスキップされます。)
JinSnow

1
@JinSnow &はを意味する特殊文字ですstop this command and start another one。を含むファイル名は引用符で& 囲む必要があります。
Jesse Chisholm

65

%1... %nおよび%*引数を保持しますが、コンテンツが解釈されるため、それらにアクセスするのは難しい場合があります。
したがって、通常のステートメントでこのようなことを処理することは不可能です

myBatch.bat "&"^&

cmd.exeがアンパサンドの1つを実行しようとするため、各行が失敗します(%1の内容はです"&"&

set var=%1
set "var=%1"
set var=%~1
set "var=%~1"

しかし、一時ファイルの回避策があります

@echo off
SETLOCAL DisableDelayedExpansion

SETLOCAL
for %%a in (1) do (
    set "prompt=$_"
    echo on
    for %%b in (1) do rem * #%1#
    @echo off
) > param.txt
ENDLOCAL

for /F "delims=" %%L in (param.txt) do (
  set "param1=%%L"
)
SETLOCAL EnableDelayedExpansion
set "param1=!param1:*#=!"
set "param1=!param1:~0,-2!"
echo %%1 is '!param1!'

コツは、ステートメントecho on%1後を有効にして展開することremです(%2 ..%*でも機能します)。
ただし、の出力をリダイレクトできるようにするにはecho on、2つのFOR-LOOPSが必要です。

余分な文字* #は、/?(REMのヘルプを表示する)などのコンテンツに対して安全であるために使用されます。
または、行末のキャレット^は複数行文字として機能する可能性があります。

FOR / Fは遅延拡張をオフにして動作するはずです。それ以外の場合は「!」破壊されます。
で余分な文字を削除した後、param1それを手に入れました。

param1安全に使用するには、遅延拡張を有効にします。

編集:%0への1つの注釈

%0バッチの呼び出しに使用されるコマンドが含まれ、同様に大文字と小文字が保持されFoO.BaT
ますが、関数の呼び出し後、関数名(または関数の呼び出しに使用された文字列)%0%~0含まれます。
しかし、%~f0あなたはまだファイル名を思い出すことができます。

@echo off
echo main %0, %~0, %~f0
call :myLabel+xyz
exit /b

:MYlabel
echo func %0, %~0, %~f0
exit /b

出力

main test.bat, test.bat, C:\temp\test.bat
func :myLabel+xyz, :myLabel+xyz, C:\temp\test.bat

6
+++ 1 OMG- %~f0トリックは完全に予期せず、クールで、非常に役立つ可能性があります。これは独自のQ&Aに値するようです-「呼び出されたサブルーチンで実行中のバッチの名前にアクセスする方法は?」
dbenham 2012年

私が正しく覚えている場合は、引数付きの呼び出しを使用できます。これらは、スクリプトを実行するときと同じように、%1、%2、...%nに格納されます。
Nulano 2014年

49

次回、これらの情報を調べる必要があるときに気づきました。ブラウザを開いてグーグルで表示する代わりcall /?に、コマンドを入力するだけで取得できます。

...

%* in a batch script refers to all the arguments (e.g. %1 %2 %3
    %4 %5 ...)

Substitution of batch parameters (%n) has been enhanced.  You can
now use the following optional syntax:

    %~1         - expands %1 removing any surrounding quotes (")
    %~f1        - expands %1 to a fully qualified path name
    %~d1        - expands %1 to a drive letter only
    %~p1        - expands %1 to a path only
    %~n1        - expands %1 to a file name only
    %~x1        - expands %1 to a file extension only
    %~s1        - expanded path contains short names only
    %~a1        - expands %1 to file attributes
    %~t1        - expands %1 to date/time of file
    %~z1        - expands %1 to size of file
    %~$PATH:1   - searches the directories listed in the PATH
                   environment variable and expands %1 to the fully
                   qualified name of the first one found.  If the
                   environment variable name is not defined or the
                   file is not found by the search, then this
                   modifier expands to the empty string

The modifiers can be combined to get compound results:

    %~dp1       - expands %1 to a drive letter and path only
    %~nx1       - expands %1 to a file name and extension only
    %~dp$PATH:1 - searches the directories listed in the PATH
                   environment variable for %1 and expands to the
                   drive letter and path of the first one found.
    %~ftza1     - expands %1 to a DIR like output line

In the above examples %1 and PATH can be replaced by other
valid values.  The %~ syntax is terminated by a valid argument
number.  The %~ modifiers may not be used with %*

20

スクリプトへのすべての引数を取得する方法は次のとおりです。

@ECHO off
ECHO The %~nx0 script args are...
for %%I IN (%*) DO ECHO %%I
pause

2
実際に%%Iは解釈されず、スクリプトが壊れる可能性があります。
Boris Brodski 2017年

5

argsを取得し、それらをenv varsとして設定するかなり簡単な方法を次に示します。この例では、それらを単にキーと値と呼びます。

次のコード例を「args.bat」として保存します。次に、保存したバッチファイルをコマンドラインから呼び出します。例:arg.bat --x 90 --y 120

プロセスをステップごとに実行するためのエコーコマンドをいくつか提供しました。ただし、最終的な結果として、-xの値は90になり、-yの値は120になります(つまり、上記で指定した例を実行した場合;-))。

次に、 'if defined'条件ステートメントを使用して、コードブロックを実行するかどうかを決定できます。「arg.bat --x hello-world」と実行すると、「IF DEFINED --x echo%-x%」というステートメントを使用でき、結果は「hello-world」になります。バッチを実行する方が理にかなっているはずです。

@setlocal enableextensions enabledelayedexpansion
@ECHO off
ECHO.
ECHO :::::::::::::::::::::::::: arg.bat example :::::::::::::::::::::::::::::::
ECHO :: By:      User2631477, 2013-07-29                                   ::
ECHO :: Version: 1.0                                                         ::
ECHO :: Purpose: Checks the args passed to the batch.                        ::
ECHO ::                                                                      ::
ECHO :: Start by gathering all the args with the %%* in a for loop.          ::
ECHO ::                                                                      ::
ECHO :: Now we use a 'for' loop to search for our keys which are identified  ::
ECHO :: by the text '--'. The function then sets the --arg ^= to the next    ::
ECHO :: arg. "CALL:Function_GetValue" ^<search for --^> ^<each arg^>         ::
ECHO ::                                                                      ::
ECHO ::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::

ECHO.

ECHO ::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
ECHO :: From the command line you could pass... arg.bat --x 90 --y 220       ::
ECHO ::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
ECHO.
ECHO.Checking Args:"%*"

FOR %%a IN (%*) do (
    CALL:Function_GetValue "--","%%a" 
)

ECHO.
ECHO ::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
ECHO :: Now lets check which args were set to variables...                   ::
ECHO ::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
ECHO.
ECHO ::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
ECHO :: For this we are using the CALL:Function_Show_Defined "--x,--y,--z"   ::
ECHO ::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
ECHO.
CALL:Function_Show_Defined "--x,--y,--z"
endlocal
goto done

:Function_GetValue

REM First we use find string to locate and search for the text.
echo.%~2 | findstr /C:"%~1" 1>nul

REM Next we check the errorlevel return to see if it contains a key or a value
REM and set the appropriate action.

if not errorlevel 1 (
  SET KEY=%~2
) ELSE (
  SET VALUE=%~2
)
IF DEFINED VALUE (
    SET %KEY%=%~2
    ECHO.
    ECHO ::::::::::::::::::::::::: %~0 ::::::::::::::::::::::::::::::
    ECHO :: The KEY:'%KEY%' is now set to the VALUE:'%VALUE%'                     ::
    ECHO :::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
    ECHO.
    ECHO %KEY%=%~2
    ECHO.
    REM It's important to clear the definitions for the key and value in order to
    REM search for the next key value set.
    SET KEY=
    SET VALUE=
)
GOTO:EOF

:Function_Show_Defined 
ECHO.
ECHO ::::::::::::::::::: %~0 ::::::::::::::::::::::::::::::::
ECHO :: Checks which args were defined i.e. %~2
ECHO :::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
ECHO.
SET ARGS=%~1
for %%s in (%ARGS%) DO (
    ECHO.
    ECHO :::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
    ECHO :: For the ARG: '%%s'                         
    IF DEFINED %%s (
        ECHO :: Defined as: '%%s=!%%s!'                                             
    ) else (
        ECHO :: Not Defined '%%s' and thus has no value.
    )
    ECHO :::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
    ECHO.
)
goto:EOF

:done

これはとても便利です!
robe007

3

ここに画像の説明を入力してください

ループを使用してすべての引数を取得するには、純粋なバッチで:

Obs:なしで使用する場合:?*&<>


@echo off && setlocal EnableDelayedExpansion

for %%Z in (%*)do set "_arg_=%%Z" && set/a "_cnt+=1+0" && call set "_arg_[!_cnt!]=!_arg_!")

:: write/test these arguments/parameters ::
for /l %%l in (1 1 !_cnt!)do echo/ The argument n:%%l is: !_arg_[%%l]!

goto :eof 

あなたのコードはそれが必要とする引数番号で何かをする準備ができています...

@echo off && setlocal EnableDelayedExpansion

for %%Z in (%*)do set "_arg_=%%Z" && set/a "_cnt+=1+0" && call set "_arg_[!_cnt!]=!_arg_!"

echo= !_arg_[1]! !_arg_[2]! !_arg_[2]!> log.txt

2

次のコードは配列( ' params')をシミュレートします-スクリプトが受け取ったパラメーターを受け取り、それらを変数に格納しますparams_1.. params_nn= params_0=配列の要素の数:

@echo off

rem Storing the program parameters into the array 'params':
rem Delayed expansion is left disabled in order not to interpret "!" in program parameters' values;
rem however, if a parameter is not quoted, special characters in it (like "^", "&", "|") get interpreted at program launch
set /a count=0
:repeat
    set /a count+=1
    set "params_%count%=%~1"
    shift
    if defined params_%count% (
        goto :repeat
    ) else (
        set /a count-=1
    )    
set /a params_0=count

rem Printing the program parameters stored in the array 'params':
rem After the variables params_1 .. params_n are set with the program parameters' values, delayed expansion can
rem be enabled and "!" are not interpreted in the variables params_1 .. params_n values
setlocal enabledelayedexpansion
    for /l %%i in (1,1,!params_0!) do (
        echo params_%%i: "!params_%%i!"
    )
endlocal

pause
goto :eof

1

スペースを含む引用符で囲まれたパラメータがある場合、%*は正しく機能しません。私が見つけた最良の解決策は、すべての引数を結合するループを持つことです:https : //serverfault.com/a/22541

set args=%1
shift
:start
if [%1] == [] goto done
set args=%args% %1
shift
goto start

:done
(use %args% here)

1

ForCommad を使用して、Argのリストを取得できます。

ヘルプ:For /? ヘルプ:Setlocal /?

これが私のやり方です=

@echo off
::For Run Use This = cmd /c ""Args.cmd" Hello USER Scientist etc"
setlocal EnableDelayedExpansion
set /a Count=0
for %%I IN (%*) DO (
 Echo Arg_!Count! = %%I
 set /a Count+=1 
)
Echo Count Of Args = !Count!
Endlocal

Shiftコマンドは必要ありません。


0
@エコーオフ
:開始

::ここにコードを挿入します
echo。%% 1は現在:%〜1
::ここにコードを挿入します

"%〜2" NEQの場合 ""(
    シフト
    goto:start
)

0

上記の情報の多くが私をさらに調査し、最終的には私の答えに導いたので、他の誰かを助けることを願って、私が巻き込んだことを貢献したいと思いました。

  • また、さまざまな数の変数をバッチファイルに渡して、ファイル内で処理できるようにしたいと考えました。

  • 引用符を使用してバッチファイルに渡しても大丈夫でした

  • 私はそれらを以下のように処理したいと思います-しかし、手動で書き出す代わりにループを使用します:

だから私はこれを実行したかった:

prog_ZipDeleteFiles.bat "_appPath=C:\Services\Logs\PCAP" "_appFile=PCAP*.?"

そしてforループの魔法を介して、これをバッチファイル内で実行します。

set "_appPath=C:\Services\Logs\PCAP"
set "_appFile=PCAP*.?"

私が抱えていた問題は、forループを使用するすべての試みが機能しなかったことです。以下の例:

for /f "tokens* delims= " in %%A (%*) DO (
   set %%A
)

ただ行うでしょう:

set "_appPath=C:\Services\Logs\PCAP"

ではなく:

set "_appPath=C:\Services\Logs\PCAP"
set "_appFile=PCAP*.?"

設定後も

SETLOCAL EnableDelayedExpansion

理由は、forループが行全体を読み取り、ループの最初の反復中に2番目のパラメーターを%% Bに割り当てたためです。%*はすべての引数を表すため、処理する行は1つだけです。これは仕様によるものであり、私の論理は間違っていました。

したがって、forループの使用をやめ、if、shift、およびgotoステートメントを使用して、実行しようとしていたことを簡略化しました。それは少しハックに同意しましたが、それは私のニーズにより適しています。すべての引数をループ処理し、ifステートメントを使用して、すべての引数を処理したらループから抜けることができます。

私が達成しようとしていたことの勝利の声明:

echo on
:processArguments
:: Process all arguments in the order received
if defined %1 then (
    set %1
    shift
    goto:processArguments
) ELSE (
    echo off 
)

更新-代わりに以下に変更する必要がありました。%1を参照しようとするときにこの方法でシフトを使用すると、すべての環境変数が公開されていました。

echo on
shift
:processArguments
:: Process all arguments in the order received
if defined %0 then (
    set %0
    shift
    goto:processArguments
) ELSE (
    echo off 
)

私は間違っています。さらにチェックを行い、3回目の反復の後、shiftコマンドはすべての環境変数を公開します。それを回避する方法があるかどうか私はまだ調べています。
John Ahearn

%1を使用する代わりに変更を加える必要があったため、最初に一度シフトして%0を使用する必要がありました。そうしないと、最終的に%1にすべての現在の環境変数が含まれるという奇妙な問題が発生しました。
John Ahearn

0

場合によっては、いくつかのコマンドラインパラメータを抽出する必要がありますが、すべてではなく、最初のパラメータからではありません。次の呼び出しを想定します。

Test.bat uno dos tres cuatro cinco seis siete

もちろん、拡張子「.bat」は必要ありません。少なくとも、同じフォルダにtest.exeがあります。出力が "tres cuatro cinco"になるようにします(1行でも3行でも)。目標は、3つのパラメーターだけが必要で、3番目のパラメーターから開始することです。簡単な例を示すために、それぞれのアクションは単なる「エコー」ですが、選択したパラメータに対する他のより複雑なアクションを考えることができます。

私はいくつかの例(オプション)を作成しましたが、どれがあなたにとってより良いと思うかを見ることができるようにしています。残念ながら、「for %% i in(%3、1、%5)」のような範囲のforループに基づく良い(または私が知らない)方法はありません。

@echo off 
setlocal EnableDelayedExpansion

echo Option 1: one by one (same line)
echo %3, %4, %5
echo.

echo Option 2: Loop For one by one
for %%a in (%3, %4, %5) do echo %%a
echo.

echo Option 3: Loop For with check of limits
set i=0
for %%a in (%*) do (
    set /A i=i+1
    If !i! GTR 2 if !i! LSS 6 echo %%a
)
echo.

echo Option 4: Loop For with auxiliary list
for /l %%i in (3,1,5) do  (
    set a=%%i
    set b=echo %%
    set b=!b!!a!
    call !b!
)
echo.

echo Option 5: Assigning to an array of elements previously
set e[0]=%0
set i=0 
for %%a in (%*) do (
    set /A i=i+1
    set e[!i!]=%%a
)
for  /l %%i in (3,1,5) do (
    echo !e[%%i]!
)
echo.

echo Option 6: using shift and goto loop. It doesn't work with for loop
set i=2
:loop6
    set /A i=i+1
    echo %3
    shift
    If %i% LSS 5 goto :loop6

おそらく、より多くのオプションを見つけるか、いくつかのオプションを組み合わせることができます。それらをお楽しみください。


-1

Windowsバージョン(socatが必要です)

C:\Program Files (x86)\Git\bin>type gitproxy.cmd
socat STDIO PROXY:proxy.mycompany.de:%1:%2,proxyport=3128

設定:

C:\Users\exhau\AppData\Roaming\npm>git config --global core.gitproxy gitproxy.cmd
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.