DOSバッチファイルにIFブロックを含めることはできますか?


96

DOSバッチファイルでは、if文の本文は1行しかありません。Cのようなプログラミング言語で使用されているのと()同じようにifブロックに使用できる場所を見つけたと思います{}が、これを試してもステートメントは実行されません。エラーメッセージもありません。この私のコード:

if %GPMANAGER_FOUND%==true(echo GP Manager is up
goto Continue7
)
echo GP Manager is down
:Continue7

不思議なことに、バッチファイルを実行すると、「GPマネージャーが起動している」も「GPマネージャーが停止している」も出力されません。


多分これかもしれないのヘルプ:commandwindows.com/batchfiles-branching.htm
esaj

ええ、それは役に立ちます。DOSはひどい。ifステートメントで複数のステートメントを使用する場合、またはステートメント間で&&を使用する必要がある場合はどうすればよいですか?またはよりエレガントな方法はありますか?
ヒューダーリン

回答:


139

実際に、条件の後に実行するステートメントのブロックを作成できます。しかし、構文が間違っています。括弧は、示されているとおりに使用する必要があります。

if <statement> (
    do something
) else (
    do something else
)

ただし、else-ifステートメントに組み込み構文があるとは思いません。残念ながらif、それを処理するにはステートメントのネストされたブロックを作成する必要があります。


第二に、その%GPMANAGER_FOUND% == trueテストは私にとって非常に疑わしく見えます。環境変数が何に設定されているか、またはどのように設定しているかはわかりませんが、表示したコードが目的の結果を生成するかどうかは非常に疑わしいです。


次のサンプルコードは私にとってはうまくいきます:

@echo off

if ERRORLEVEL == 0 (
    echo GP Manager is up
    goto Continue7
)
echo GP Manager is down
:Continue7

私のサンプルコードに関するいくつかの特定の詳細に注意してください:

  • 条件ステートメントの終わりと開き括弧の間に追加されたスペース。
  • 私は、実行時にコンソールに出力されるすべてのステートメント@echo off表示しないように設定しています。代わりに、特に次で始まるステートメントの出力を表示します。echo
  • 組み込みERRORLEVEL変数をテストとして使用しています。詳細はこちら

1
IF ERRORLEVEL <N>がtrueであるため、他のバリアントは常にtrueであるため、%ERRORLEVEL%== 0の場合に使用するのがより良い。errorlevelが<N>以上の場合、この場合、「==」は無視される
jeb

@jeb:要点を見逃したかもしれません。使用ERRORLEVELは彼の問題への答えではありません。私は単に適切な構文の例を投稿していました。この場合、他の平凡な表現と同じように、どちらの形式でも受け入れられif 0 == 0ます。ただし、実際には、環境変数%ERRORLEVEL%ERRORLEVELコマンドプロセッサの内部の違いを理解していることを確認してください。レイモンド・チェンはこのブログでそれをうまく説明しています
コーディグレイ

ELSE IFはありますか?
xagyg 2013

1
@mythofechelonのコメントに加えて、REMステートメントで一見無害な閉じ括弧でさえブロックを終了します。例えばREM This is a comment (or so I thought)IFブロックに投げると、あなたはめちゃくちゃになります。
rkagerer

2
@mythofechelonと@rkagererはどちらも、文字列を引用する必要があるという一般的なルールの特定の問題を指摘しています。どちらの文字列オペランドの特殊文字もステートメントで構文エラーを引き起こさないIF %somevar%==example_string2 ように、オペランドはIF "value_of_somevar"=="example_string2"に解決されるよう常にコーディング する必要があります IF。設定した値は常に実行する必要があります。 set "somevar=value_of_somevar" この構文では変数値の特殊文字をエスケープできます。注私が意味するものではありません set somevar="value_of_somevar"
スキップR

15

論理的には、コーディの答えうまくいくはずです。ただし、コマンドプロンプトがコードブロックを論理的に処理するとは思いません。私の人生では、ブロック内の1つ以上のコマンドでそれを適切に機能させることはできません。私の場合、広範なテストの結果、ブロック内のすべてのコマンドがキャッシュされ、ブロックの最後で同時に実行されていることがわかりました。もちろん、これは期待した結果にはなりません。これは単純化しすぎた例です:

if %ERRORLEVEL%==0 (
set var1=blue
set var2=cheese
set var3=%var1%_%var2%
)

これにより、var3に次の値提供されます。

blue_cheese

しかし、代わりに以下が得られます:

_

3つのコマンドすべてがキャッシュされ、コードブロックの終了時に同時に実行されるためです。

ifブロックを1つのコマンド(goto)のみを実行するように書き直し、いくつかのラベルを追加することで、この問題を克服することができました。その不格好で、私はあまり好きではありませんが、少なくともそれは機能します。

if %ERRORLEVEL%==0 goto :error0
goto :endif

:error0
set var1=blue
set var2=cheese
set var3=%var1%_%var2%

:endif

8
遅延拡張の使用は機能するはずです。使用:set var3=!var1!_!var2!
Dracorat 2013年

4

このgotoの混乱の代わりに、アンパーサンド&またはダブルアンパーサンド&&(エラーレベル0の条件付き)をコマンドの区切り文字として使用してみてください。

このトリックを使用してスクリプトスニペットを修正しました。要約すると、3つのバッチファイルがあり、1つは外部バックアップドライブが割り当てられている文字を見つけた後に他の2つを呼び出します。最初のファイルをプライマリ外部ドライブに残しているので、そのバックアップルーチンへの呼び出しは正常に機能しましたが、2番目のファイルへの呼び出しにはアクティブなドライブの変更が必要でした。以下のコードは、それをどのように修正したかを示しています。

for %%b in (d e f g h i j k l m n o p q r s t u v w x y z) DO (
if exist "%%b:\Backup.cmd" %%b: & CALL "%%b:\Backup.cmd"
)

なぜこれが反対投票なのですか?これはまさに私が必要としたものです。
ggb667 2014年

1
@ GCB667-「@Louis」を明確にするために、IFステートメントが元のポスターで機能しなかった理由の問題に関係のない「回答」を書きました。 。
スキップR

1

バッチファイル内のIFコマンドに関連する検索によって返された結果でこの記事に出くわしましたが、IFブロックが単一のコマンドに制限されているという誤解を訂正する機会に抵抗できませんでした。以下は、この応答を作成しているマシンで毎日実行される実動Windows NTコマンドスクリプトの一部です。

    if "%COPYTOOL%" equ "R" (
    WWLOGGER.exe "%APPDATA%\WizardWrx\%~n0.LOG" "Using RoboCopy to make a backup of %USERPROFILE%\My Documents\Outlook Files\*"
    %TOOLPATH% %SRCEPATH% %DESTPATH% /copyall %RCLOGSTR% /m /np /r:0 /tee
    C:\BIN\ExitCodeMapper.exe C:\BIN\ExitCodeMapper.INI[Robocopy] %TEMP%\%~n0.TMP %ERRORLEVEL%
) else (
    WWLOGGER.exe "%APPDATA%\WizardWrx\%~n0.LOG" "Using XCopy to make a backup of %USERPROFILE%\My Documents\Outlook Files\*"
    call %TOOLPATH%  "%USERPROFILE%\My Documents\Outlook Files\*" "%USERPROFILE%\My Documents\Outlook Files\_backups" /f /m /v /y
    C:\BIN\ExitCodeMapper.exe C:\BIN\ExitCodeMapper.INI[Xcopy] %TEMP%\%~n0.TMP %ERRORLEVEL%
)

おそらく、2行以上のブロックは、Windows NTコマンドスクリプト(.CMDファイル)にのみ適用されます。古い学校のバッチ(.BAT)ファイルに制限されているアプリケーションの本番スクリプトディレクトリを検索すると、1つのコマンドブロックしか明らかにならないためです。 。アプリケーションが拡張メンテナンスになっている(つまり、サポートに積極的に関与していない)ため、それが必要だったのが1行だけだったのか、それとも機能させることができなかったのかはわかりません。

いずれにしても、後者が当てはまる場合は、簡単な回避策があります。複数の行を個別のバッチファイルまたはバッチファイルサブルーチンに移動します。後者は両方の種類のスクリプトで機能することを知っています。


0

多分少し遅れますが、それがうまくいくことを願っています:

@echo off 

if %ERRORLEVEL% == 0 (
msg * 1st line WORKS FINE rem You can relpace msg * with any othe operation...
goto Continue1
)
:Continue1
If exist "C:\Python31" (
msg * 2nd line WORKS FINE rem You can relpace msg * with any othe operation...
    goto Continue2
)
:Continue2
If exist "C:\Python31\Lib\site-packages\PyQt4" (  
msg * 3th line WORKS FINE rem You can relpace msg * with any othe operation...
    goto Continue3
)
:Continue3
msg * 4th line WORKS FINE rem You can relpace msg * with any othe operation...
    goto Continue4
)
:Continue4
msg * "Tutto a posto" rem You can relpace msg * with any othe operation...
pause
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.