相关文章推荐
谦和的苦瓜  ·  jar包服务 java ...·  8 小时前    · 
逃跑的小刀  ·  specify sysctl values ...·  1 年前    · 
低调的警车  ·  Spring ...·  1 年前    · 
私奔的绿豆  ·  flutter - ...·  1 年前    · 
个性的手套  ·  理解 ...·  1 年前    · 
Collectives™ on Stack Overflow

Find centralized, trusted content and collaborate around the technologies you use most.

Learn more about Collectives

Teams

Q&A for work

Connect and share knowledge within a single location that is structured and easy to search.

Learn more about Teams

I need to test if a variable is set or not. I've tried several techniques but they seem to fail whenever %1 is surrounded by quotes such as the case when %1 is "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.

According to this site, these are the supported IF syntax types. So, I don't see a way to do it.

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

UPDATE: on 2020-10-25, I updated the accepted answer from using brackets to using a tilde. Everyone says the tilde is better as it's more secure. I'm a little torn cause the tilde looks more complicated and is less clear as to what it's purpose is but nevertheless, I changed it.

On my systems (Windows 2003 as well as Windows 7), if "%1" == "" GOTO MyLabel doesn't fatally kill the execution of the script as long as %1 has an even number of double-quotes. I see that an odd number of double-quotes in %1 kills the execution of the script with this error: The syntax of the command is incorrect. The solution below that uses square brackets to solve the problem has been marked as the correct answer but it doesn't seem to be doing any better. That solution also fails with the same error when %1 has an odd number of double-quotes. – Susam Pal Jan 7, 2013 at 14:31 @SusamPal Interesting. Try the parenthesis version under it and see if that works. That one I tested more. I just updated the accepted answer a couple days ago. – blak3r Jan 7, 2013 at 18:25 a good "catch all" example: stackoverflow.com/questions/830565/… covering both file/directory and generic string/number mix in argument. – user257319 Jan 1, 2016 at 1:48 So frustrating -- IF DEFINED only working on environment variables instead of script variables is such a waste of potential! – kayleeFrye_onDeck Aug 16, 2016 at 23:04 Using other characters like if #%1#==## or if [%1]==[] is good so long as there are no spaces in the argument, otherwise you will get a …was unexpected at this time error. – Synetech Feb 4, 2013 at 19:41 Guys, @jamesdlin is correct. This approach will not work if the variable text has spaces or is ==. Use his answer instead. – James Ko Apr 3, 2016 at 15:36 You do not make it clear that it DOES NOT work with spaces. Use @jamesdlin answer instead. – JB. Jun 12, 2017 at 11:56 This is indeed a good way to do it. By using ~, you strip the outer quotes if they are present, but then add them back manually (ensuring only one set). Moreover, you have to use quotes if the argument contains spaces (I learned this the hard way when my previous version of using # or brackets instead of quotes caused arguments with spaces to throw a …was unexpected at this time error.) – Synetech Feb 4, 2013 at 19:39 is this also applicable for general variables like %MYVAR% rather than the arguments like %1 ? – simpleuser Aug 17, 2017 at 19:52 watch out for strings that use double '"' as an escape sequence -- the script will crash when attempting the comparison. E.g. ""this string will crash the comparison"". Double '"' is the proper escape sequence, and doing a substitution on double '"' will fail if the string is empty. – Tydaeus Oct 26, 2017 at 2:46 @Amalgovinus You probably could pass the variable as an argument to a subroutine and let the subroutine use "%~1". – jamesdlin Jul 11, 2019 at 2:09

One of the best semi solutions is to copy %1 into a variable and then use delayed expansion, as delayedExp. is always safe against any content.

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

The advantage of this is that dealing with param1 is absolutly safe.

And the setting of param1 will work in many cases, like

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

But it still fails with strange contents like

test.bat ^&"&

To be able to get a 100% correct answer for the existence

It detects if %1 is empty, but for some content it can't fetch the content.
This can be also be useful to distinguish between an empty %1 and one with "".
It uses the ability of the CALL command to fail without aborting the batch file.

@echo off
setlocal EnableDelayedExpansion
set "arg1="
call set "arg1=%%1"
if defined arg1 goto :arg_exists
set "arg1=#"
call set "arg1=%%1"
if "!arg1!" EQU "#" (
    echo arg1 exists, but can't assigned to a variable
    REM Try to fetch it a second time without quotes
    (call set arg1=%%1)
    goto :arg_exists
echo arg1 is missing
exit /b
:arg_exists
echo arg1 exists, perhaps the content is '!arg1!'

If you want to be 100% bullet proof to fetch the content, you could read How to receive even the strangest command line parameters?

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

......

The DEFINED conditional works just like EXISTS except it takes an environment variable name and returns true if the environment variable is defined.

Yes, I actually tried this approach and from what I could tell this only works with ENVIRONMENT variables. Therefore, didn't work with %1 or a variable defined inside the batch file. – blak3r Mar 31, 2010 at 14:23 That is only true for %1 and the likes. "Variables defined inside the batch file" actually are environment variables while the batch file is running, and you can use IF DEFINED on them. – zb226 Mar 1, 2013 at 13:20

Unfortunately I don't have enough reputation to comment or vote on the current answers to I've had to write my own.

Originally the OP's question said "variable" rather than "parameter", which got very confusing, especially as this was the number one link in google for searching how to test for blank variables. Since my original answer, Stephan has edited the original question to use the correct terminology, but rather than deleting my answer I decided to leave it to help clear up any confusion, especially in case google is still sending people here for variables too:

%1 IS NOT A VARABLE! IT IS A COMMAND LINE PARAMETER.

Very important distinction. A single percent sign with a number after it refers to a command line parameter not a variable.

Variables are set using the set command, and are recalled using 2 percent signs - one before and one after. For example %myvar%

To test for an empty variable you use the "if not defined" syntax (commands explicitly for variables do not require any percent signs), for example:

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.

(If you want to test command line parameters then I recommend referring to jamesdlin's answer.)

you are right. But the correct way would have been to just correct the title from if variable is empty to if parameter is empty. I just did it. (at the risk to invalidate some of the answers, which did check variables instead of parameters and so are invalid anyway, as they didn't answer the question) – Stephan Jul 24, 2018 at 16:02 OK thanks Stephan, didn't realise you could do that. I've edited my answer to reflect the update. – AutoMattTick Jul 27, 2018 at 14:20 Welcome to SO! Your reply does seem a good answer to the question. Once you have sufficient [reputation] (stackoverflow.com/help/whats-reputation) you will be able to comment on any post. Also check this what can I do instead. – thewaywewere Apr 26, 2017 at 1:18

Use "IF DEFINED variable command" to test variable in batch file.

But if you want to test batch parameters, try below codes to avoid tricky input (such as "1 2" or ab^>cd)

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

I created this small batch script based on the answers here, as there are many valid ones. Feel free to add to this so long as you follow the same format:

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
                Your solution fails when the variable contains a quote. Btw there exists the syntax IF DEFINED var for a reason
– jeb
                Mar 6, 2018 at 15:51
                This is incorrect.  This is the same thing as: IF "%1" == "" the reason for this post was if %1 itself has quotes this fails.
– blak3r
                Mar 31, 2010 at 14:21
                Are you trying to test if %1 is empty or if it has quotes? The question is unclear. My answer works if nothing is specified on the command line for %1.
– aphoria
                Mar 31, 2010 at 18:41
                > Are you trying to test if %1 is empty or if it has quotes?   @aphoria, it has to be able to handle both.
– Synetech
                Oct 21, 2012 at 16:17
                aphoria - forgive the 10-years-later response but I just read this today. To expand on what @blak3r said... For example, your batch file is named batch.cmd. In the simplest terms, you execute: batch.cmd ". That is, only one parameter consisting of one double-quote mark. Or batch.cmd ab"cd, or anything more complex, generally described as having an odd number of ["] marks. Your statement: IF "%1."=="." GOTO MyLabel will fail and cause the batch execution to end (crash), usually with error: The syntax of the command is incorrect., because the ["] marks can't be matched.
– Kevin Fegan
                Sep 3, 2020 at 22:59

then test it's 2 characters against double-quotes:

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

Here's a batch script you can play with. I think it properly catches the empty string.

This is just an example, you just need to customize 2 (or 3?) steps above according to your 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% %*

This torture test result:

.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" " "< "">"  (")(") "" :: ""-"  " "( )"">\>" ""
                It's wrong, an empty string isn't a string with two double quotes "" an empty string is an empty string `` and in batch an empty variable is an undefined variable. You can define, that for your arguments the outer quotes will be removed, but then the string is still empty with a length of 0
– jeb
                Oct 4, 2016 at 7:51
                In this context (win cmd arguments), you can not denote an empty string with any other way, not even with double single-quote which equally empty under unix shell.
– user6801759
                Oct 5, 2016 at 14:55
                Yes, "" are used for empty strings too, but it's quite easy to use %~1 to remove the outer quotes. there is no need to use such a complex solution
– jeb
                Oct 6, 2016 at 12:56
                You right, I might improperly stated, it not just for empty string but a safe way to enumerate arguments. Other ways such as "%~1"=="" will fail with argument like "Long File Name".txt which is a valid argument. edit: And it's definitely not complex as you said. Only 2 steps above for test, the rest are verbose example.
– user6801759
                Oct 7, 2016 at 4:28
                "if not defined ARG" seems to work perfectly (my variable doesn't come from command line)
– GrayFace
                Jan 11, 2017 at 8:43
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

Output (There is none, %1 was NOT blank, empty, or NULL):

Run ("Remove Quotes.cmd") without any parameters with the above script 1

Output (%1 is blank, empty, or NULL):

Welcome!
Press any key to continue . . .

Note: If you set a variable inside an IF ( ) ELSE ( ) statement, it will not be available to DEFINED until after it exits the "IF" statement (unless "Delayed Variable Expansion" is enabled; once enabled use an exclamation mark "!" in place of the percent "%" symbol}.

For example:

Script 2:

Input ("Remove Quotes.cmd" "This is a Test")

@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

Output:

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>  

Note: It will also remove quotes from inside the string.

For Example (using script 1 or 2): C:\Users\Test\Documents\Batch Files>"Remove Quotes.cmd" "This is "a" Test"

Output (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  

I've had a lot of issues with a lot of answers on the net. Most work for most things, but there's always a corner case that breaks each one.
Maybe it doesn't work if it's got quotes, maybe it breaks if it doesn't have quotes, syntax error if the var has a space, some will only work on parameters (as opposed to environment variables), other techniques allow an empty set of quotes to pass as 'defined', and some trickier ones won't let you chain an else afterward.

Here's a solution I'm happy with, please let me know if you find a corner case it won't work for.

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

Having that subroutine either in a your script, or in it's own .bat, should work.
So if you wanted to write (in pseudo):

if (var)
then something
else somethingElse

You can write:

(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

More examples:

  • Wanna just check if? Call :ifSet %var% && Echo set
  • Just if not (only the else)? Call :ifSet %var% || Echo set
  • Checking a passed argument; works fine. Call :ifSet %1 && Echo set
  • Didn't want to clog up your scripts/dupe code, so you put it in it's own ifSet.bat? No problem: ((Call ifSet.bat %var%) && Echo set) || (Echo not set)
  • Found a case; If you try the if with else syntax, and the last command in the then block fails, the else will execute: (Call ifSet.bat YES && (Echo true & Echo x | findstr y)) || Echo, echos true and false – Hashbrown Aug 4, 2016 at 1:31 Actually, if this is an issue, and you can deal with an extra line, you can mitigate this by calling ifSet on its own, then using If %errorlevel% EQU 0 (x) Else (y) – Hashbrown Aug 4, 2016 at 7:45 What cases does the accepted answer (use square brackets) not work on? And can you explain what the Exit /B does – blak3r Aug 7, 2016 at 18:17 for some reason when I tested it broke when using set variables (like [%bob%], only working for arguments like [%2]) but now rechecking it works. I guess my only gripe with [] now is it lets empty quotes pass, whereas this wont (so it's up to your use case, really) – Hashbrown Aug 12, 2016 at 3:39 The /B flag stops the whole batch from exiting, only exiting the subroutine or call'd batch. Unless you're asking what the whole command is doing; it's returning an error code to let the calling script know the result of the subroutine (0 pass, 1 fail), usable via boolean logic in the answer, or via %errorlevel% in the above comments – Hashbrown Aug 12, 2016 at 3:43 The tip is really bad. Quotes can handle spaces and special characters at least, but exclamation marks can't. And exclamation marks get really nasty here when delayed expansion is enabled – jeb Mar 6, 2018 at 17:35 if "%~1" == "" if [%1] == [] echo Argument 1 is really empty. First filter (if "%~1" == "") из safe way to detect argument is empty or "". Second filter (if [%1] == []) will skip "" argument. Remember we have two kind of empty arguments : really empty (nothing) and empty quotes "". We have to detect both. Next code takes all arguments "as is" in variable args: :GetArgs set args=%1 :ParseArgs shift /1 if "%~1" == "" if [%1] == [] goto :DoneArgs set args=%args% %1 goto :ParseArgs :DoneArgs if not defined args echo No arguments if defined args echo Aguments are: %args% This code correctly process "normal" arguments (simple words, "multiword phrases" or "") with balanced quotes. Quoted arguments can even contain special chars like "a & b". But it is still can fail with "abnormal" expressions with unbalanced quotes (do not use them). But it fails with a syntax error for myBatch ^&. Btw. Using [] is useless, they have no special meaning and can't escape anything. – jeb Oct 7, 2021 at 15:45 You're right. My example only check if variable exist, not if it is empty. I misunderstood topic task. – alive-one Mar 3, 2022 at 5:13

    I got in in just under a month old (even though it was asked 8 years ago)... I hope s/he's moved beyond batch files by now. ;-) I used to do this all the time. I'm not sure what the ultimate goal is, though. If s/he's lazy like me, my go.bat works for stuff like that. (See below) But, 1, the command in the OP could be invalid if you are directly using the input as a command. i.e.,

    "C:/Users/Me"
    

    is an invalid command (or used to be if you were on a different drive). You need to break it in two parts.

    cd /Users/Me

    And, 2, what does 'defined' or 'undefined' mean? GIGO. I use the default to catch errors. If the input doesn't get caught, it drops to help (or a default command). So, no input is not an error. You can try to cd to the input and catch the error if there is one. (Ok, using go "downloads (only one paren) is caught by DOS. (Harsh!))

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

    And, 3, quotes are needed only around the path, not the command. i.e.,

    "cd C:\Users" 
    

    was bad (or used to in the old days) unless you were on a different drive.

    cd "\Users" 
    

    is functional.

    cd "\Users\Dr Whos infinite storage space"
    

    works if you have spaces in your path.

    @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
                    there is a reason for cd's /d switch: cd /d "C:\Users\Me" (and the proper path delimeter for Windows is `, not /).
    – Stephan
                    Jul 24, 2018 at 15:58
                    It's a long post, but doesn't even try to answer the question. It's about how to detect empty arguments, not what could be a default behaviour for an empty argument
    – jeb
                    Oct 8, 2021 at 6:25
            

    Thanks for contributing an answer to Stack Overflow!

    • Please be sure to answer the question. Provide details and share your research!

    But avoid

    • Asking for help, clarification, or responding to other answers.
    • Making statements based on opinion; back them up with references or personal experience.

    To learn more, see our tips on writing great answers.