「.bat」ファイルのコマンドラインパラメータを確認する方法


103

私のOSはWindows Vistaです。ユーザーがコマンドラインパラメータを入力したかどうかを確認する必要がある「.bat」ファイルが必要です。もしそうなら、もしパラメータが-b次に等しいなら、私は何かをします。そうでなければ、「無効な入力」にフラグを立てます。ユーザーがコマンドラインパラメータを入力しない場合は、何かを行います。以下の.batファイルを作成しました。これは動作し-b、等しくはありません-bが、ユーザーがコマンドラインパラメータを渡さないと失敗します。

私はいつもエラーになります:

GOTO was unexpected at this time.

誰かが私がここで間違っていることを教えてもらえますか?


ECHO OFF
CLS
ECHO.

IF [%1]==[/?] GOTO BLANK

IF %1=="-b" GOTO SPECIFIC

IF NOT %1=="-b" GOTO UNKNOWN

:SPECIFIC

ECHO SPECIFIC

GOTO DONE

:BLANK

ECHO No Parameter

GOTO DONE

:UNKNOWN

ECHO Unknown Option

GOTO DONE

:DONE

ECHO Done!

GOTO BLANK他の2つのIFステートメントに(行のように)角かっこを追加すると、問題が解決しますか?
エレミヤウィルコック

回答:


141

パラメータが空白かどうかを確認する必要があります。 if "%~1"=="" goto blank

それが終わったら、if / elseスイッチを-bでオンにします。 if "%~1"=="-b" (goto specific) else goto unknown

パラメータを引用符で囲むと、空白/空/欠落しているパラメータなどのチェックが簡単になります。「〜」は、コマンドライン引数にある場合、二重引用符が削除されることを保証します。


これはうまくいく!「else」のみは受け入れられません。「else」は、内部または外部コマンド、操作可能なプログラム、またはバッチファイルとして認識されません。そこで、「-bと等しくない」場合に別のIFを追加しました。素早い回答ありがとうございます。
javauser71

7
ELSEはIFと同じ行にある必要があります。または、ブラケットの直後になければなりません
jeb

4
%1にスペースが含まれている場合、これは機能しないようです。これは、実行可能ファイルへの完全なパスである場合に当てはまる可能性があります。値にスペースが含まれるパラメーターでも機能する解決策については、Jeremiah Willcockの回答を参照してください。
マークA.フィッツジェラルド

引数がの場合は受け入れられません。Fileその場合は、existまたはのみをチェックする必要がありますnot exist。これは、あなたの引数が明確に定義された、または単にPowerShellのまたはVBScriptを使用しなければならない理由です(あなたが80年代にしている場合。)

1
これは失敗しrun.bat "a b"ます。"%1"==""argにスペースがあるとクラッシュします。stackoverflow.com/a/46942471を
wisbucky '25年

27

答えはhttp://ss64.com/nt/if.htmlを見てください。コマンドはIF [%1]==[] GOTO NO_ARGUMENT似ています。


1
これも機能するだけではありません!とは対照的に、機能し"%1"==""ます。私自身の答えでそれについて詳しく説明する必要があります。
Tomasz Gandor

1
これは、%1が引用符で囲まれている場合は壊れfoo.bat "1st parameter" 2nd_paramます。stackoverflow.com/questions/2541767/…を
マットウィルキー

[%1]==[-b]argが引用符で囲まれている場合、使用は一致しません。例run.bat "-b"stackoverflow.com/a/46942471を
wisbucky '25年

20

短い答え-角括弧を使用します:

if [%1]==[] goto :blank

または(引用符付きの引数を処理する必要がある場合は、以下の編集を参照してください):

if [%~1]==[] goto :blank

どうして?あなたが尋ねるかもしれません。まあ、ちょうどエレミヤ・ウィルコックが言ったように:言った http彼らはそれを使用します!わかりましたが、引用符の何が問題になっていますか?

繰り返しになりますが、短い答え:それらは「魔法」です-二重(二重)引用符が単一(二重)引用符に変換されることがあります。そして、それらは最初に一致する必要があります。

この小さなスクリプトを考えてみましょう:

@rem argq.bat
@echo off

:loop 
if "%1"=="" goto :done
echo %1
shift
goto :loop

:done
echo Done.

それをテストしましょう:

C:\> argq bla bla
bla
bla
Done.

動作するようです。しかし、今、セカンドギアに切り替えましょう:

C:\> argq "bla bla"
bla""=="" was unexpected at this time.

ブームこれはtrueと評価されず、falseと評価されませんでした。スクリプトDIED。あなたがラインのどこかで原子炉をオフにすることになっていたなら、まあ-頑張ってください。あなたはハリー・ダリアンのように死ぬでしょう。

あなたは考えるかもしれません-OK、引数に引用符を含めることはできません。もしそうなら、これは起こります。間違っていますここにいくつかの慰めがあります:

C:\> argq ""bla bla""
""bla
bla""
Done.

そうそう。心配しないでください- これうまくいくことがあります。

別のスクリプトを試してみましょう:

@rem args.bat
@echo off

:loop 
if [%1]==[] goto :done
echo %1
shift
goto :loop

:done
echo Done.

上記のケースで問題なく動作することを自分でテストできます。これは論理的です-引用符は大括弧とは関係がないため、ここには魔法はありません。しかし、括弧を使って引数をスパイクするのはどうですか?

D:\>args ]bla bla[
]bla
bla[
Done.

D:\>args [bla bla]
[bla
bla]
Done.

運がありません。ブラケットは窒息できないcmd.exeのパーサーを。

ちょっと邪悪な引用に戻りましょう。議論が引用符で終わったときに問題がありました:

D:\>argq "bla1 bla2"
bla2""=="" was unexpected at this time.

私がちょうど合格した場合:

D:\>argq bla2"
The syntax of the command is incorrect.

スクリプトはまったく実行されません。同じargs.bat

D:\>args bla2"
The syntax of the command is incorrect.

しかし"、そのような場合、-文字の数が「一致する」(つまり-が偶数である)場合、何が得られますか。

D:\>args bla2" "bla3
bla2" "bla3
Done.

NICE-.batファイルがコマンドライン引数を分割する方法について何か学んだことを願っています(ヒント:* bashの場合とはまったく異なります)。上記の引数にはスペースが含まれています。しかし、引用符は自動的に取り除かれません。

そしてargq?それはどのように反応しますか?予想通り:

D:\>argq bla2" "bla3
"bla3"=="" was unexpected at this time.

だから-あなたが言う前に考えてください:「何を知っているのですか?引用符を使ってください。[私にとって、これはより見栄えが良いので]」。

編集する

最近、この回答についてのコメントがありました。まあ、sqareブラケットは引用符で囲まれた引数を渡して、引用符で囲まれていないかのように処理することは「処理できません」。

構文:

if "%~1"=="" (...)

二重引用符によって新しく発見されたいくつかの美徳ではありませんが、最初と最後の文字が二重引用符である場合、引数変数から引用符を取り除くというきちんとした機能の表示です。

この「テクノロジー」は、角かっこでも同様に機能します。

if [%~1]==[] (...)

これを指摘することは有益だったので、新しい答えにも賛成します。

最後に、ファンを二重引用符で囲み""ます。フォームの引数はあなたの本に存在しますか、それとも空白ですか?ちょうど同じ;)


1
[%1]==[-b]argがのように引用されている場合、角括弧は一致しませんrun.bat "-b"stackoverflow.com/a/46942471を
wisbucky '25年

歴史的に注意してください:[%1]==[-b]そして"%1"=="-b"勝利98と以前のMS / PC-DOSシステムのバッチスクリプトと同じでした。勝利2000 / NT以降if "%~1"=="-b"、二重引用符が特別な意味を持つ構文が導入されました。これは、より堅牢な保護を提供するため、スクリプトをコーディングする方法です。二重引用符は、特殊文字の意味をエスケープします(コマンドラインで&&および%文字を試してください)。例の99.9%は二重引用符構文で機能します-あなたの例argq bla2" "bla3は角括弧を正当化する場合のみです。埋め込まれた二重引用符は、災害のレシピです-ただ言うだけです
Skip R

@SkipR-そのため、Windowsのファイルシステムでは、名前にこれらの特殊文字を含めることはできません。私は数学的な証明はありませんが、cmdシェルですべてを引用できるわけではないと思います(ある意味で-エスケープシーケンスなどで逐語的に作成される)。他のシステムでは、NUL文字を含めて、すべてを引用できる場合があります。(stackoverflow.com/questions/2730732/…)-この質問は、外部プログラムを使用する必要があることを示しています。
Tomasz Gandor 2017年

8

私がサブスクライブする他の回答に加えて/IIFコマンドのスイッチを使用することを検討できます。

... / Iスイッチを指定すると、大文字と小文字を区別しない文字列比較を行うように指示されます。

ユーザーがパラメータを指定する際に、大文字と小文字を区別しない柔軟性を提供する場合に役立ちます。

IF /I "%1"=="-b" GOTO SPECIFIC

5

文字列を比較しています。引数が省略されている場合、%1コマンドがIF =="-b" GOTO SPECIFICたとえば(構文エラー)になるように空白に展開されます。文字列を引用符(または角括弧)で囲みます。

REM this is ok
IF [%1]==[/?] GOTO BLANK

REM I'd recommend using quotes exclusively
IF "%1"=="-b" GOTO SPECIFIC

IF NOT "%1"=="-b" GOTO UNKNOWN

IF [%1] == [/?]は機能しませんが、IF [%1] == []または "%1" == ""を実行すると機能します。とにかく今私は行くことができます。早速の対応、ありがとうございました。
javauser71

5

実際、他のすべての回答には欠陥があります。最も信頼できる方法は次のとおりです。

IF "%~1"=="-b" (GOTO SPECIFIC) ELSE (GOTO UNKNOWN)

詳細な説明:

使用"%1"=="-b"スペースや引用符で引数を渡す場合は平らにクラッシュします。これは最も信頼性の低い方法です。

IF "%1"=="-b" (GOTO SPECIFIC) ELSE (GOTO UNKNOWN)

C:\> run.bat "a b"

b""=="-b" was unexpected at this time.

[%1]==[-b]スペースと引用符でクラッシュしないため、使用する方が優れていますが、引数が引用符で囲まれていると一致しません。

IF [%1]==[-b] (GOTO SPECIFIC) ELSE (GOTO UNKNOWN)

C:\> run.bat "-b"

(does not match, and jumps to UNKNOWN instead of SPECIFIC)

使用するの"%~1"=="-b"が最も信頼できます。%~1存在する場合は、周囲の引用符を取り除きます。したがって、引用符の有無にかかわらず、引数なしでも機能します。

IF "%~1"=="-b" (GOTO SPECIFIC) ELSE (GOTO UNKNOWN)

C:\> run.bat
C:\> run.bat -b
C:\> run.bat "-b"
C:\> run.bat "a b"

(all of the above tests work correctly)

1
これは角括弧の終わりではありません。次のように表示されます。- IF [%~1]==[]これは機能し、も処理し"-b"ます。あなたは箱の中で考えることができればいいのです。
Tomasz Gandor 2017年

3

最近、バッチファイルでの複雑なパラメータースイッチの実装に苦労してきたので、これが私の研究の結果です。提供された回答はどれも完全に安全ではありません。例:

"%1"=="-?" パラメータが引用符で囲まれている場合は一致しません(ファイル名などに必要)。パラメータが引用符で囲まれていてスペースがある場合はクラッシュします(これもファイル名でよく見られます)。

@ECHO OFF
SETLOCAL
echo.
echo starting parameter test...
echo.
rem echo First parameter is %1
if "%1"=="-?" (echo Condition is true, param=%1) else (echo Condition is false, param=%1)
C:\>test.bat -?

starting parameter test...

Condition is true, param=-?

C:\>test.bat "-?"

starting parameter test...

Condition is false, param="-?"

角括弧との任意の組み合わせ、[%1]==[-?]または[%~1]==[-?]パラメーターが引用符内にスペースがある場合は失敗します。

@ECHO OFF
SETLOCAL 
echo.
echo starting parameter test...
echo.
echo First parameter is %1
if [%~1]==[-?] (echo Condition is true, param=%1) else (echo Condition is false, param=%1)

C:\>test.bat "long file name"

starting parameter test...

First parameter is "long file name"
file was unexpected at this time.

提案されている最も安全なソリューション"%~1"=="-?"は、引用符の外側のテキストと引用符の内側にスペースがあるテキストを含む複雑なパラメーターでクラッシュします。

@ECHO OFF
SETLOCAL 
echo.
echo starting parameter test...
echo.
echo First parameter is %1
if "%~1"=="-?" (echo Condition is true, param=%1) else (echo Condition is false, param=%1)

C:\>test.bat -source:"long file name"

starting parameter test...

First parameter is -source:"long file name"
file was unexpected at this time.

上記のすべてのシナリオを確実にカバーする唯一の方法は、EnableDelayedExpansionを使用し、変数を使用して(値ではなく)参照によってパラメーターを渡すことです。そうすれば、最も複雑なシナリオでも問題なく機能します。

@ECHO OFF
SETLOCAL EnableDelayedExpansion
echo.
echo starting parameter test...
echo.
echo First parameter is %1
:: we assign the parameter to a variable to pass by reference with delayed expansion
set "var1=%~1"
echo var1 is !var1!
:: we assign the value to compare with to a second variable to pass by reference with delayed expansion
set "var2=-source:"c:\app images"\image.png"
echo var2 is !var2!
if "!var1!"=="!var2!" (echo Condition is true, param=!var1!) else (echo Condition is false, param=!var1!)
C:\>test.bat -source:"c:\app images"\image.png

starting parameter test...

First parameter is -source:"c:\app images"\image.png
var1 is -source:"c:\app images"\image.png
var2 is -source:"c:\app images"\image.png
Condition is true, param=-source:"c:\app images"\image.png

C:\>test.bat -source:"c:\app images"\image1.png

starting parameter test...

First parameter is -source:"c:\app images"\image1.png
var1 is -source:"c:\app images"\image1.png
var2 is -source:"c:\app images"\image.png
Condition is false, param=-source:"c:\app images"\image1.png

C:\>test.bat -source:"c:\app images\image.png"

starting parameter test...

First parameter is -source:"c:\app images\image.png"
var1 is -source:"c:\app images\image.png"
var2 is -source:"c:\app images"\image.png
Condition is false, param=-source:"c:\app images\image.png"

0

Windowsバッチには、これを行うためのDEFINEDキーワードがあります。

IF DEFINED %~1 foo
IF NOT DEFINED %~1 bar

デビッドありがとう。IFとIF NOTの間にキャリッジリターンと改行がなかった理由がわかりません。私も気づかなかった。
チャールズ
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.