Discussion:
BATch files, the maddening irrationalities thereof ...
(too old to reply)
Java Jive
2024-05-08 09:17:34 UTC
Permalink
Consider a first code fragment for getting command-line parameters at
the start of a BATch file, everything works as it should:


:NextPar
IF %Debug% NEQ "" ECHO Parameter="%1"
IF /i "%1" EQU "/D" (
SET Debug="Y"
SHIFT
GOTO NextPar
)
IF /i "%1" EQU "/N" (
SET Dummy="Y"
SHIFT
GOTO NextPar
)
IF /i "%1" EQU "/S" (
SET ListSources="Y"
SHIFT
GOTO NextPar
)
IF %Debug% NEQ "" ECHO Debugging output ...
IF %Dummy% NEQ "" ECHO Dummy run, NOT actually making changes ...
IF %ListSources% NEQ "" ECHO Only listing sources ...


D:\Temp>fh /d /n /s

Parameter="/n"
Parameter="/s"
Parameter=""
Debugging output ...
Dummy run, NOT actually making changes ...
Only listing sources ...
Sources=<Correct hard coded CSV list of \\Server\Shares>
Known servers are:
<Correct list>


However, add in a section of code to add another possible command-line
parameter to replace the hard-coded list with a list of local drive
designations, and it fails unexpectedly:


IF /i "%1" EQU "/L" (
SHIFT
SET LocSources="%1"
IF %Debug% NEQ "" ECHO ">>>LocSources = '%LocSources%'<<<" & ECHO
">>>Parameter = '%1'<<<"
SHIFT
GOTO NextPar
)


10:15:10 D:\Temp>fh /d /n /s /l D:

Parameter="/n"
Parameter="/s"
Parameter="/l"
">>>LocSources = ''<<<"
">>>Parameter = '/l'<<<"
Parameter=""
Debugging output ...
Dummy run, NOT actually making changes ...
Only listing sources ...
Using only local sources '"/l"' ...

Known servers are:
"/l"

So the SET command fails to give LocSources any value, and the first
SHIFT in the new section is being completely ignored.

WTF?
--
Fake news kills!

I may be contacted via the contact address given on my website:
www.macfh.co.uk
R.Wieser
2024-05-08 10:01:33 UTC
Permalink
Java,
So the SET command fails to give LocSources any value, and the first SHIFT
in the new section is being completely ignored.
Not quite. Move the "/s" argument to the end and notice its correctly
detected. IOW, the shift is executed - just not when you expect it. :-|

A few quick-ish tests show that if you put a goto to the next line just
after the shift its recognised when you do the assignment.

Also, *not* using "(", ")" but just (old style) jumping over that block of
code also causes the shift to be recognised as it should.

IOW, there is some kind of odd (or just unknown) interference with
manipulating the arguments inside a(n unnamed) subroutine.

By the way, I tested on XP, mening its an old bug(?)

Regards,
Rudy Wieser

p.s.
Did you know that SHIFT has got zero effect on %* ? Yeah, didn't expect
that either.
VanguardLH
2024-05-08 14:35:45 UTC
Permalink
Post by Java Jive
IF /i "%1" EQU "/L" (
SHIFT
SET LocSources="%1"
IF %Debug% NEQ "" ECHO ">>>LocSources = '%LocSources%'<<<" & ECHO ">>>Parameter = '%1'<<<"
SHIFT
GOTO NextPar
)
I remember something about where you have to change when the vars get
expanded (parsed). Within the scope of an if- or for-loop, too late for
expansion which was done at the start of the command, not within the
command. You could try:

cmd.exe /v:on ...

when you load the shell in which to run the batch script, but then you
use !var! isntead of %var%. Since it is on env vars, you would have to
do the shift and set commands together to copy %1 into %var% (oops,
maybe !var!).

Or use:

setlocal enabledelayedexpansion

within the batch script. For help, run: setlocal /?. Some more help:

https://ss64.com/nt/delayedexpansion.html
"Delayed Expansion will cause variables within a batch file to be
expanded at execution time rather than at parse time, this option is
turned on with the SETLOCAL EnableDelayedExpansion command."

The 'if' is considered one line, but you are shifting inside it. When
you exit the 'if' which did a 'shift', the next command using the parm
will get the expanded (shifted) value, but not within the 'if' where you
tried to shift twice and use the shifted value (expanded).

https://learn.microsoft.com/en-us/windows-server/administration/windows-commands/setlocal

This is just something I remember that can affect var expansion within a
batch script. Maybe this has to do with the effect you notice.
Java Jive
2024-05-08 18:25:41 UTC
Permalink
Post by VanguardLH
Post by Java Jive
IF /i "%1" EQU "/L" (
SHIFT
SET LocSources="%1"
IF %Debug% NEQ "" ECHO ">>>LocSources = '%LocSources%'<<<" & ECHO ">>>Parameter = '%1'<<<"
SHIFT
GOTO NextPar
)
I remember something about where you have to change when the vars get
expanded (parsed). Within the scope of an if- or for-loop, too late for
expansion which was done at the start of the command, not within the
cmd.exe /v:on ...
when you load the shell in which to run the batch script, but then you
use !var! isntead of %var%. Since it is on env vars, you would have to
do the shift and set commands together to copy %1 into %var% (oops,
maybe !var!).
setlocal enabledelayedexpansion
https://ss64.com/nt/delayedexpansion.html
"Delayed Expansion will cause variables within a batch file to be
expanded at execution time rather than at parse time, this option is
turned on with the SETLOCAL EnableDelayedExpansion command."
The 'if' is considered one line, but you are shifting inside it. When
you exit the 'if' which did a 'shift', the next command using the parm
will get the expanded (shifted) value, but not within the 'if' where you
tried to shift twice and use the shifted value (expanded).
https://learn.microsoft.com/en-us/windows-server/administration/windows-commands/setlocal
This is just something I remember that can affect var expansion within a
batch script. Maybe this has to do with the effect you notice.
Yes, thank you for taking the trouble to reply, although I was aware of
most of what you wrote, and you weren't able to suggest an actual fix,
which is what I was hoping someone might be able to do.

As I suggested and you seem to agree, the whole thing's an illogical
PITA ...

What seems to be happening is that both within FOR loops and IF
statements, maybe also within parentheses (), a new copy of the
environment is created, but what happens to changes to that environment
both during the execution of such a statement and after its end is
somewhat ad hoc - changes made to the values of *pre-existing* (note
carefully what is emphasised) variables seem not to be available within
the statement, accessing them within it yields their original values on
entry to the statement, but seem to survive beyond the bounds of it,
suggesting that those changes were made in the original environment, not
the copy. Eh?! So why bother to make the copy in the first place?!
However, variables created within the statement are lost on exit from
it, suggesting that those changes occurred within the copied
environment! Unsurprisingly, the result is an inconsistent and
unpredictable mess.

However, as regards the current problem, I've got round it simply by
negating the sense of the IF statement:


IF /i "%1" NEQ "/S" GOTO HellOrWherever
SHIFT
SET Sources="%~1"
IF %Debug% NEQ "" ECHO ">>>Sources = '%Sources%'<<<" & ECHO
">>>Parameter = '%1'<<<"
SHIFT
GOTO NextPar


D:\Temp>Test /d /n /s /l "D:,F:"

Parameter="/d"
Parameter="/n"
Parameter="/s"
Parameter="/l"
">>>Sources = '"D:,F:"'<<<"
">>>Parameter = '"D:,F:"'<<<"
Parameter=""
Debugging output ...
Dummy run, NOT actually making changes ...
Only listing sources ...
Sources="D:,F:"
Known servers are:
D:
F:

Another day wasted on Microshit's illogicality.
--
Fake news kills!

I may be contacted via the contact address given on my website:
www.macfh.co.uk
R.Wieser
2024-05-09 06:49:44 UTC
Permalink
Java,
Post by Java Jive
However, as regards the current problem, I've got round it simply
Yep.

An even simpler work-around would have been to use " SET LocSources="%2" and
move both SHIFTs together to just before the GOTO.

... which also makes more sense from a logical POV.

Regards,
Rudy Wieser

Loading...