web-dev-qa-db-ja.com

バッチファイルで複数のIFステートメントを使用する

複数のIFステートメントを使用する場合、従うべき特別なガイドラインはありますか?グループ化する必要がありますか?括弧を使用してコマンドをラップする必要がありますか?

使用例は次のとおりです。

IF EXIST somefile.txt IF EXIST someotherfile.txt SET var=somefile.txt,someotherfile.txt
15
Mechaflash

従うべき特別なガイドラインはありますか

バッチファイルを作成するための "標準"の方法はありません。作成者とメンテナーの大多数はプログラミングの概念を理解していないか、バッチファイルに適用しないと考えているためです。

しかし、私はプログラマーです。私はコンパイルに慣れており、デバッガーにも慣れています。バッチファイルはコンパイルされず、デバッガーを介して実行することもできないため、緊張します。あなたが書くものに非常に厳しいことをお勧めしますので、あなたはそれがあなたがそれが思うと思うことをすることを非常に確信することができます。

いくつかのコーディング標準があります:ifステートメントを記述する場合は、else句がなくても中括弧を使用する必要があります。これにより、微妙なデバッグしにくい問題からあなたを救い、明確に読みやすくなります。この推論をバッチファイルに適用できなかった理由はありません。

コードを見てみましょう。

IF EXIST somefile.txt IF EXIST someotherfile.txt SET var=somefile.txt,someotherfile.txt

コマンドからのIF構文、HELP IF

IF [NOT] ERRORLEVEL number command
IF [NOT] string1==string2 command
IF [NOT] EXISTS filename command

...

IF EXIST filename (
  command
) ELSE (
  other command
)

したがって、IFをコマンドとしてチェーンします。

上記の一般的なコーディング標準ルールを使用する場合は、常に括弧を使用する必要があります。サンプルコードの場合、次のようにします。

IF EXIST "somefile.txt" (
  IF EXIST "someotherfile.txt" (
    SET var="somefile.txt,someotherfile.txt"
  )
)

きれいにフォーマットし、何らかの形のインデントを行うようにしてください。コードでそれを行い、バッチスクリプトでそれを行う必要があります。

また、ファイル名を常に引用し、正しく引用する習慣を身に付ける必要があります。 HELP FORおよびHELP SETの下には、文字列を再引用するときに余分な引用符を削除するのに役立ついくつかの冗長性があります。

編集

コメントから、元の質問を読み直して、存在するファイルのコンマ区切りリストを作成したいようです。この場合、単にif/elseステートメントの束を使用できますが、それは重複したロジックの束になり、2つ以上ある場合はまったくクリーンになりません。ファイル。

より良い方法は、単一のファイルの存在をチェックし、指定されたファイルが存在する場合に変数に追加する サブルーチンを書く です。次に、チェックするファイルごとにそのサブルーチンを呼び出します。

@ECHO OFF
SETLOCAL

REM Todo: Set global script variables here
CALL :MainScript
GOTO :EOF

REM MainScript()
:MainScript
  SETLOCAL

  CALL :AddIfExists "somefile.txt" "%files%" "files"
  CALL :AddIfExists "someotherfile.txt" "%files%" "files"

  ECHO.Files: %files%

  ENDLOCAL
GOTO :EOF

REM AddIfExists(filename, existingFilenames, returnVariableName)
:AddIfExists
  SETLOCAL

  IF EXIST "%~1" (
    SET "result=%~1"
  ) ELSE (
    SET "result="
  )

  (
    REM Cleanup, and return result - concatenate if necessary
    ENDLOCAL

    IF "%~2"=="" (
      SET "%~3=%result%"
    ) ELSE (
      SET "%~3=%~2,%result%"
    )
  )
GOTO :EOF
31

上記のMerlynによる説明はかなり完全です。ただし、コーディング標準について詳しく説明したいと思います。

複数のIFがチェーンされている場合、前の条件がすべて満たされたときに最終コマンドが実行されます。これはAND演算子と同等です。私は時々この動作を使用しましたが、ANDと呼ばれる補助的なバッチ変数を介して、意図することを明確に示しています。

SET AND=IF

IF EXIST somefile.txt %AND% EXIST someotherfile.txt SET var=somefile.txt,someotherfile.txt

もちろん、これは真のAnd演算子ではないため、ELSE句と組み合わせて使用​​しないでください。これは、めったに使用されない命令の読みやすさを向上させるための単なるプログラマー支援です。

バッチプログラムを書くときは、より読みやすいコードを書くことを唯一の目的として設計したいくつかの補助変数を常に使用します。例えば:

SET AND=IF
SET THEN=(
SET ELSE=) ELSE (
SET NOELSE=
SET ENDIF=)
SET BEGIN=(
SET END=)
SET RETURN=EXIT /B

Merlynが示唆したように、これらの変数はバッチプログラムをより明確に記述するのに役立ち、微妙なエラーを回避するのに役立ちます。例えば:

IF EXIST "somefile.txt" %THEN%
  IF EXIST "someotherfile.txt" %THEN%
    SET var="somefile.txt,someotherfile.txt"
  %NOELSE%
  %ENDIF%
%NOELSE%
%ENDIF%

IF EXIST "%~1" %THEN%
  SET "result=%~1"
%ELSE%
  SET "result="
%ENDIF%

WHILE-DOやREPEAT-UNTILのような構造を作成するのに役立つ変数もあります。これは、バッチ変数をプリプロセッサ値としてある程度使用できることを意味します。

11
Aacini

バッチファイルのロジック機能は非常に限られているため、思い付くことができる最善の方法は、目的を間接的に達成する適切な回避策です。それは、実際の言語よりも劣っていると感じるべきだということではありません。実際のアプリケーションと同様に、詳細と手動のデバッグに同じ注意を払う必要があります。それはあなたが彼らがあなたが望むことを堅牢な方法で行うためにあなたがもっと一生懸命働く必要があるということだけです。

OPの質問については、2つの特定のファイルが存在する必要があるようです。集計を使用するだけです:

IF EXIST somefile.txt (
    set /a file1_status=1
)

IF EXIST someotehrfile.txt (
    set /a file2_status=1
)

set /a file_status_result=file1_status + file2_status

if %file_status_result% equ 2 (
    goto somefileexists
)

goto exit

:somefileexists
IF EXIST someotherfile.txt SET var=...

:exit

私の例では3つの変数を使用していますが、ファイルが存在する場合はfile_result_statusに1を追加するだけで済みます。ただし、バッチファイルで後により細かな制御が必要な場合は、各ファイルの結果を記録することができます。これにより、後でファイルが存在するかどうかを確認する必要がなくなります。

5
studotwho
IF EXIST "somefile.txt" (
  IF EXIST "someotherfile.txt" (
    SET var="somefile.txt","someotherfile.txt"
  )
) ELSE (
  CALL :SUB
)
:SUB
ECHO Sorry... nothin' there.
GOTO:EOF

これは可能ですか?

SETLOCAL ENABLEDELAYEDEXPANSION
IF EXIST "somefile.txt" (
  SET var="somefile.txt"
  IF EXIST "someotherfile.txt" (
    SET var=!var!,"someotherfile.txt"
  )
) ELSE (
  IF EXIST "someotherfile.txt" (
    SET var="someotherfile.txt"
  ) ELSE (
  GOTO:EOF
  )
)
3
Mechaflash

Gotoを使用して、バッチファイルを構造化できます。

IF EXIST somefile.txt goto somefileexists
goto exit

:somefileexists
IF EXIST someotherfile.txt SET var=...

:exit
1
Mike Mozhaev