It's important when using %1 to put something around it to prevent the batch file from breaking when %1 is empty, because %1 isn't a variable it gets substituted with the value, like SQL injection an example of injection in batch, and when the value is nothing, and the %1 is in an IF, then you get broken code. if %1==""
becomes if == ""
and gives an error.
As for why if defined doesn't work on %1, %1 is the value not the variable so hence defined doesn't work there. For code that works for %1 being empty you need code that won't break when %1 is substituted with nothing. Try if "%1"==""
or try if [%1]==[]
To say -%1 does look a bit confusing, it doesn't look like a good convention to me! Technically you could even do if a%1==a%1
or if %1a==%1a
but convention tends to be []
You can use quotes, or [] or whatever character(s). But as supercat has pointed out in comment, quotes are not a good idea around a %1. (Because if the %1 contains spaces, the user include quotes in what gets passed to be %1, and if there is a space in the %1 and in the batch file you put quotes around the %1, the quotes will cancel out and the unquoted space there will cause an error ).
If you were doing an IF on the command line and not testing any variable, you'd have no %1 and you'd not even need []. You'd say IF "a b c"=="a b c" echo a
or IF a==b echo a
If in a batch file then you often have %1, and rather than use quotes around the %1, use e.g. one or two characters around it e.g. [%1]
and use quotes if you need to preserve spaces and it's not a %1 e.g. e.g. IF [%1]==[a]
or IF [%1]==["a b"] echo a
Don't do "%1"
because the %1 might already have quotes which your quotes will cancel out and then if the %1 has a space your if statement breaks.
If you were on the command line and were testing a variable then it depends whether the variable has quotes. You can look at the contents.
It is possible for a variable to have a space and not contain quotes.
So in this particular command line case, putting quotes around %a% will not double quotes, and you have to put quotes around the %a% if you want to test it against "a b"
C:\>set a=a b
C:\>echo %a%
a b
C:\>IF %a%=="a b" echo sdf
b=="a b" was unexpected at this time.
C:\>IF "%a%"=="a b" echo sdf
sdf
So ^^^ we want "%a%"
Whereas if %a% contained quotes, it'd be a different case
C:\>set a="a b"
C:\>echo %a%
"a b"
C:\>IF %a%=="a b" echo a
a
C:\>IF "%a%"=="a b" echo a
b""=="a b" was unexpected at this time.
C:\>
^^^^ So there we want %a% without quotes around it.
So it's all a question of whether the variable or parameter contains quotes. If the %1 has spaces in it then it will contain quotes. So we know that if we were comparing %1 to "a b" then w wouldn't do "%1". And if %1 didn't contain quotes it wouldn't contain spaces, so we wouldn't do "%1" So I think you'd never want to do "%1". So, if %1 contains spaces, there will be quotes within the %1 and the spaces will already be preserved.
I crossed out the below in light of supercat's comment. And I added more to my post above.
Quotes are best around the %1, rather than [] or some character like A or -, because for example, if you use [] then it won't preserve spaces
C:\>if [d a b]==[d a b] echo sdf
a was unexpected at this time.
Say if "d a b"
that will work. So if "%1"
is better than other character(s) like if [%1]
or a%1a
or -%1
for %1 in (*.*) do @echo %1
and it'd be ambiguous to do that in a batch file so for statements when within a batch file use %% but batch parameters (which btw are only ever in a batch file), are always %1,%2 etc