Подтвердить что ты не робот

Использование нескольких операторов IF в пакетном файле

При использовании более 1 оператора IF существует ли специальное руководство, которое должно соблюдаться? Должны ли они быть сгруппированы? Должен ли я использовать скобки для переноса команд (ов)?

Пример использования:

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

Ответ 1

существует специальная рекомендация, которой следует следовать

Нет стандартного способа делать пакетные файлы, потому что подавляющее большинство их авторов и сопровождающих либо не понимают концепций программирования, либо считают, что они не применяются к пакетным файлам.

Но я программист. Я привык к компиляции, и я привык к отладчикам. Пакетные файлы не скомпилированы, и вы не можете запускать их через отладчик, поэтому они заставляют меня нервничать. Я предлагаю вам быть более строгим в отношении того, что вы пишете, поэтому вы можете быть уверены, что он будет делать то, что, по вашему мнению, делает.

Существуют некоторые стандарты кодирования, которые говорят: если вы пишете оператор 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 как команды.

Если вы используете стандартное правило стандартного кодирования, о котором я упоминал выше, вы всегда хотели бы использовать parens. Вот как вы могли бы сделать это для своего примера кода:

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

Удостоверьтесь, что вы четко форматируете и выполняете какую-то форму отступа. Вы делаете это в коде, и вы должны делать это в своих пакетных сценариях.

Кроме того, вы также должны иметь привычку всегда ссылаться на ваши имена файлов и получать право на цитаты. Существует несколько слов в HELP FOR и HELP SET, которые помогут вам удалить лишние кавычки при повторном цитировании строк.

Edit

Из ваших комментариев и повторного чтения исходного вопроса кажется, что вы хотите создать список файлов, разделенных запятыми, которые существуют. В этом случае вы можете просто использовать кучу операторов if/else, но это приведет к кучке дублированной логики и не будет чистым, если у вас более двух файлов.

Лучше всего написать подпрограмму, которая проверяет существование одного файла и добавляет к переменной, если указанный файл существует, Затем просто вызовите эту подпрограмму для каждого файла, который вы хотите проверить:

@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

Ответ 2

Объяснение, данное Мерлином выше, довольно полно. Однако я хотел бы остановиться на стандартах кодирования.

Когда несколько IF закодированы, последняя команда выполняется, когда все предыдущие условия встречаются; это эквивалентно оператору И. Я использовал это поведение время от времени, но я четко указываю, что я намерен делать с помощью вспомогательной переменной Batch с именем 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

Эти переменные помогают в более эффективном написании пакетных программ и помогают избежать тонких ошибок, как предположил Мерлин. Например:

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. Это означает, что пакетные переменные могут использоваться в некоторой степени как значения препроцессора.

Ответ 3

Пакетные файлы имеют очень ограниченные логические возможности, поэтому лучшее, что вы можете надеяться придумать, - это хорошее обходное решение, которое косвенно достигает того, чего вы хотите. Это не означает, что вы должны чувствовать, что они уступают реальному языку - они по-прежнему требуют такого же внимания к деталям и ручной отладки, что и реальное приложение. Это просто, что вам нужно будет работать намного сложнее, чтобы заставить их делать то, что вы хотите, надежным способом.

Для вопроса OP это звучит так, как будто вам нужны два определенных файла. Просто используйте подсчет:

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 переменные, но вы можете просто добавить 1 в файл_result_status, если файл существует. Но если вы хотите более подробный контроль позже в своем пакетном файле, вы можете записать результат для каждого файла, как я сделал, поэтому вам не нужно продолжать проверять, существует ли файл позже.

Ответ 4

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
  )
)

Ответ 5

Вы можете структурировать пакетный файл с помощью goto

IF EXIST somefile.txt goto somefileexists
goto exit

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

:exit