Каков правильный способ проверить, является ли параметр пустым в пакетном файле?

Мне нужно проверить, установлена ​​ли переменная или нет. Я пробовал несколько методов, но они, кажется, терпят неудачу, когда %1 окружен кавычками, такими как случай, когда %1 есть "c:\some path with spaces".

IF NOT %1 GOTO MyLabel // This is invalid syntax
IF "%1" == "" GOTO MyLabel // Works unless %1 has double quotes which fatally kills bat execution
IF %1 == GOTO MyLabel // Gives an unexpected GOTO error.

Согласно этому сайту, это поддерживаемые типы синтаксиса IF. Итак, я не вижу способа сделать это.

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

Ответ 1

Используйте квадратные скобки вместо кавычек:

IF [%1] == [] GOTO MyLabel

Скобки небезопасны: используйте только квадратные скобки.

Ответ 2

Вы можете использовать:

IF "%~1" == "" GOTO MyLabel

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

Ответ 3

Одним из лучших полу решений является копирование %1 в переменную, а затем использование замедленного расширения, как delayedExp. всегда безопасен для любого контента.

set "param1=%~1"
setlocal EnableDelayedExpansion
if "!param1!"=="" ( echo it is empty )
rem ... or use the DEFINED keyword now
if defined param1 echo There is something

Преимущество этого заключается в том, что обращение с param1 абсолютно безопасно.

И параметр param1 будет работать во многих случаях, например

test.bat hello"this is"a"test
test.bat you^&me

Но он будет терпеть неудачу со странным содержимым, например

test.bat "&"^&

Если вы хотите получить 99% доказательство пули, вы можете прочитать Как получить даже самые странные параметры командной строки?

Ответ 4

От IF/?:

Если расширения команд включены, ЕСЛИ изменяется следующим образом:

IF [/I] string1 compare-op string2 command
IF CMDEXTVERSION number command
IF DEFINED variable command

......

Условные работы DEFINED как EXISTS, за исключением того, что требуется имя переменной среды и возвращает true, если переменная окружения определены.

Ответ 5

Используйте команду "IF DEFINED variable" для проверки переменной в пакетном файле.

Но если вы хотите проверить параметры партии, попробуйте использовать коды ниже, чтобы избежать сложного ввода (например, "1 2" или ab ^ > cd)

set tmp="%1"
if "%tmp:"=.%"==".." (
    echo empty
) else (
    echo not empty
)

Ответ 6

Пустая строка - это пара double-quotes/"", мы можем просто проверить длину:

set ARG=%1
if not defined ARG goto nomore

set CHAR=%ARG:~2,1%
if defined CHAR goto goon

затем проверьте его на 2 символа против double-quotes:

if ^%ARG:~1,1% == ^" if ^%ARG:~0,1% == ^" goto blank
::else
goto goon

Вот пакет script, с которым вы можете играть. Я думаю, что он правильно ловит пустую строку.

Это просто пример, вам просто нужно настроить 2 (или 3?) шага выше в соответствии с вашим script.

@echo off
if not "%OS%"=="Windows_NT" goto EOF
:: I guess we need enableExtensions, CMIIW
setLocal enableExtensions
set i=0
set script=%0

:LOOP
set /a i=%i%+1

set A1=%1
if not defined A1 goto nomore

:: Assumption:
:: Empty string is (exactly) a pair of double-quotes ("")

:: Step out if str length is more than 2
set C3=%A1:~2,1%
if defined C3 goto goon

:: Check the first and second char for double-quotes
:: Any characters will do fine since we test it *literally*
if ^%A1:~1,1% == ^" if ^%A1:~0,1% == ^" goto blank
goto goon

:goon
echo.args[%i%]: [%1]
shift
goto LOOP

:blank
echo.args[%i%]: [%1] is empty string
shift
goto LOOP

:nomore
echo.
echo.command line:
echo.%script% %*

:EOF

Результат теста пыток:

.test.bat :: ""  ">"""bl" " "< "">"  (")(") "" :: ""-"  " "( )"">\>" ""
args[1]: [::]
args[2]: [""] is empty string
args[3]: [">"""bl" "]
args[4]: ["< "">"]
args[5]: [(")(")]
args[6]: [""] is empty string
args[7]: [::]
args[8]: [""-"  "]
args[9]: ["( )"">\>"]
args[10]: [""] is empty string

command line:
.test.bat :: ""  ">"""bl" " "< "">"  (")(") "" :: ""-"  " "( )"">\>" ""

Ответ 7

Я обычно использую это:

IF "%1."=="." GOTO MyLabel

Если% 1 пуст, IF сравнивает ".". к "." который будет оцениваться как истинный.

Ответ 8

Script 1:

Вход ( "Удалить Quotes.cmd" "Это тест" )

@ECHO OFF

REM Set "string" variable to "first" command line parameter
SET STRING=%1

REM Remove Quotes [Only Remove Quotes if NOT Null]
IF DEFINED STRING SET STRING=%STRING:"=%

REM IF %1 [or String] is NULL GOTO MyLabel
IF NOT DEFINED STRING GOTO MyLabel


REM   OR   IF "." equals "." GOTO MyLabel
IF "%STRING%." == "." GOTO MyLabel

REM GOTO End of File
GOTO :EOF

:MyLabel
ECHO Welcome!

PAUSE

Выход (Нет,% 1 не было пустым, пустым или NULL):


Запустить ( "Удалить Quotes.cmd" ) без каких-либо параметров с указанным выше script 1

Выход (% 1 пуст, пуст или NULL):

Welcome!

Press any key to continue . . .

Примечание. Если вы установите переменную внутри оператора IF ( ) ELSE ( ), она не будет доступна для ОПРЕДЕЛЕНА до тех пор, пока она не выйдет из оператора "IF" (если не включена опция "Отсроченное расширение переменной", после включения используйте восклицательный знак "!" вместо символа процента "%" }.

Например:

Script 2:

Вход ( "Удалить Quotes.cmd" "Это тест" )

@ECHO OFF

SETLOCAL EnableDelayedExpansion

SET STRING=%0
IF 1==1 (
  SET STRING=%1
  ECHO String in IF Statement='%STRING%'
  ECHO String in IF Statement [delayed expansion]='!STRING!'
) 

ECHO String out of IF Statement='%STRING%'

REM Remove Quotes [Only Remove Quotes if NOT Null]
IF DEFINED STRING SET STRING=%STRING:"=%

ECHO String without Quotes=%STRING% 

REM IF %1 is NULL GOTO MyLabel
IF NOT DEFINED STRING GOTO MyLabel

REM GOTO End of File
GOTO :EOF

:MyLabel
ECHO Welcome!

ENDLOCAL
PAUSE

Вывод:

C:\Users\Test>"C:\Users\Test\Documents\Batch Files\Remove Quotes.cmd" "This is a Test"  
String in IF Statement='"C:\Users\Test\Documents\Batch Files\Remove Quotes.cmd"'  
String in IF Statement [delayed expansion]='"This is a Test"'  
String out of IF Statement='"This is a Test"'  
String without Quotes=This is a Test  

C:\Users\Test>  

Примечание. Он также удалит кавы изнутри строки.

Пример (с использованием script 1 или 2):   C:\Users\Test\Documents\Batch Files > "Удалить Quotes.cmd" "Это" Тест "

Выход (Script 2):

String in IF Statement='"C:\Users\Test\Documents\Batch Files\Remove Quotes.cmd"'  
String in IF Statement [delayed expansion]='"This is "a" Test"'  
String out of IF Statement='"This is "a" Test"'  
String without Quotes=This is a Test  

Выполнить ( "Удалить Quotes.cmd" ) без каких-либо параметров в script 2:

Вывод:

Welcome!

Press any key to continue . . .

Ответ 9

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

REM Parameter-testing

Setlocal EnableDelayedExpansion EnableExtensions

IF NOT "%~1"=="" (echo Percent Tilde 1 failed with quotes) ELSE (echo SUCCESS)
IF NOT [%~1]==[] (echo Percent Tilde 1 failed with brackets) ELSE (echo SUCCESS)
IF NOT  "%1"=="" (echo Quotes one failed) ELSE (echo SUCCESS)
IF NOT [%1]==[] (echo Brackets one failed) ELSE (echo SUCCESS)
IF NOT "%1."=="." (echo Appended dot quotes one failed) ELSE (echo SUCCESS)
IF NOT [%1.]==[.] (echo Appended dot brackets one failed) ELSE (echo SUCCESS)

pause

Ответ 10

Подводя итог:

set str=%~1
if not defined str ( echo Empty string )

Этот код выведет "Пустую строку", если% 1 "или" или "Пусто". Добавил его к принятому ответу, который в настоящее время неверен.

Ответ 11

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

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

% 1 НЕ РАЗЛИЧНО! Это ПАРАМЕТР КОМАНДНОЙ ЛИНИИ.

Очень важное различие. Один знак процента с номером после него ссылается на параметр командной строки, а не на переменную.

Переменные задаются с помощью команды set и вызывается с использованием знаков 2 процента - один до и один за другим. Например,% myvar%

Чтобы проверить пустую переменную, вы используете синтаксис "if not defined" (явно для команд для переменных не требуются знаки процента), например:

set myvar1=foo  
if not defined myvar1 echo You won't see this because %myvar1% is defined.  
if not defined myvar2 echo You will see this because %myvar2% isn't defined.

(Если вы хотите проверить параметры командной строки, я рекомендую обратиться к ответу jamesdlin.)

Ответ 12

У меня было много проблем с множеством ответов в сети. Большинство работает для большинства вещей, но всегда есть угловой случай, который разбивает каждый.
Возможно, это не сработает, если оно получило кавычки, возможно, оно ломается, если у него нет кавычек, синтаксическая ошибка, если у var есть пробел, некоторые будут работать только с параметрами (в отличие от переменных среды), другие методы позволяют пустым набор кавычек для передачи как "определенный", а некоторые более сложные из них не позволят вам после этого привязать else.

Вот решение, с которым я доволен, сообщите мне, если вы найдете угловой случай, в котором он не будет работать.

:ifSet
if "%~1"=="" (Exit /B 1) else (Exit /B 0)

Если эта подпрограмма либо в вашем script, либо в ней собственном .bat, должна работать.
Поэтому, если вы хотите написать (в псевдо):

if (var)
then something
else somethingElse

Вы можете написать:

(Call :ifSet %var% && (
    Echo something
)) || (
    Echo something else
)

Он работал для всех моих тестов:

(Call :ifSet && ECHO y) || ECHO n
(Call :ifSet a && ECHO y) || ECHO n
(Call :ifSet "" && ECHO y) || ECHO n
(Call :ifSet "a" && ECHO y) || ECHO n
(Call :ifSet "a a" && ECHO y) || ECHO n

Echo'd n, y, n, y, y


Другие примеры:

  • Хотите просто проверить if? Call :ifSet %var% && Echo set
  • Просто если нет (только другое)? Call :ifSet %var% || Echo set
  • Проверка переданного аргумента; работает отлично. Call :ifSet %1 && Echo set
  • Не хотел засовывать ваш скрипт/код, так что вы поместили его в свой собственный ifSet.bat? Нет проблем: ((Call ifSet.bat %var%) && Echo set) || (Echo not set)

Ответ 13

Использование! вместо "для проверки пустой строки

@echo off
SET a=
SET b=Hello
IF !%a%! == !! echo String a is empty
IF !%b%! == !! echo String b is empty

Ответ 14

Вы можете использовать

if defined (variable) echo That defined!
if not defined (variable) echo Nope. Undefined.

Ответ 15

Я тестирую код ниже, и это нормально.

@echo off

set varEmpty=
if not "%varEmpty%"=="" (
    echo varEmpty is not empty
) else (
    echo varEmpty is empty
)
set varNotEmpty=hasValue
if not "%varNotEmpty%"=="" (
    echo varNotEmpty is not empty
) else (
    echo varNotEmpty is empty
)

Ответ 16

Я попал чуть меньше месяца (хотя это было спрошено 8 лет назад)... Надеюсь, он/она переместился за рамки пакетных файлов. ;-) Я делал это все время. Я не уверен, какова конечная цель. Если он ленив, как я, мой go.bat работает так. (См. Ниже) Но, 1, команда в OP может быть недействительной, если вы непосредственно используете ввод в качестве команды. т.е.

"C:/Users/Me"

является недопустимой командой (или используется, если вы находитесь на другом диске). Вам нужно разбить его на две части.

C:
cd /Users/Me

И, 2, что означает "определенное" или "неопределенное"? GIGO. Я использую значение по умолчанию для обнаружения ошибок. Если вход не попадает, он падает, чтобы помочь (или по умолчанию). Таким образом, вход не является ошибкой. Вы можете попробовать cd на вход и поймать ошибку, если она есть. (Хорошо, используя go "загрузки (только один паз), пойман DOS. (Harsh!))

cd "%1"
if %errorlevel% neq 0 goto :error

И, 3, цитаты нужны только по пути, а не по команде. т.е.

"cd C:\Users" 

был плохим (или использовался в старые времена), если вы не были на другом диске.

cd "\Users" 

является функциональным.

cd "\Users\Dr Whos infinite storage space"

работает, если у вас есть пробелы на вашем пути.

@REM go.bat
@REM The @ sigh prevents echo on the current command
@REM The echo on/off turns on/off the echo command. Turn on for debugging
@REM You can't see this.
@echo off
if "help" == "%1" goto :help

if "c" == "%1" C:
if "c" == "%1" goto :done

if "d" == "%1" D:
if "d" == "%1" goto :done

if "home"=="%1" %homedrive%
if "home"=="%1" cd %homepath%
if "home"=="%1" if %errorlevel% neq 0 goto :error
if "home"=="%1" goto :done

if "docs" == "%1" goto :docs

@REM goto :help
echo Default command
cd %1
if %errorlevel% neq 0 goto :error
goto :done

:help
echo "Type go and a code for a location/directory
echo For example
echo go D
echo will change disks (D:)
echo go home
echo will change directories to the users home directory (%homepath%)
echo go pictures
echo will change directories to %homepath%\pictures
echo Notes
echo @ sigh prevents echo on the current command
echo The echo on/off turns on/off the echo command. Turn on for debugging
echo Paths (only) with folder names with spaces need to be inclosed in         quotes (not the ommand)
goto :done

:docs
echo executing "%homedrive%%homepath%\Documents"
%homedrive%
cd "%homepath%\Documents"\test error\
if %errorlevel% neq 0 goto :error
goto :done

:error
echo Error: Input (%1 %2 %3 %4 %5 %6 %7 %8 %9) or command is invalid
echo go help for help
goto :done

:done