Использование нескольких операторов IF в пакетном файле - PullRequest
14 голосов
/ 15 июля 2011

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

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

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

Ответы [ 5 ]

31 голосов
/ 15 июля 2011

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

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

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

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

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

@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
11 голосов
/ 22 июля 2011

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

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

5 голосов
/ 24 июля 2013

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

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

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

3 голосов
/ 15 июля 2011
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
  )
)
1 голос
/ 15 июля 2011

Вы можете структурировать ваш пакетный файл, используя goto

IF EXIST somefile.txt goto somefileexists
goto exit

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

:exit
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...