Are there any scripts that DEPEND on NOT using Delayed Expansion?

Microsoft Windows
Post Reply
Rekrul
Posts: 52
Joined: 2021-Aug-15, 11:29 pm

Are there any scripts that DEPEND on NOT using Delayed Expansion?

Post by Rekrul »

Just a theoretical question...

I'm given to understand that Windows batch scripts don't use Delayed Expansion in order to maintain backwards compatibility with older scripts, which didn't have it. As a result, inside loops, or when inside parenthesis, only the existing value of a variable can be read. You can set the value, but you can't read it until the command finishes.

My question is: Are there actually scripts that rely on this fact?

I don't mean scripts that take this quirk into account, I mean scripts that absolutely depend on a variable's value not changing for the duration of a loop or within a multi-command block. Scripts that would not function correctly if Delayed Expansion was in effect, because the variable would give the current value, rather than the original value.

Do people write such scripts?

I've tried to think of a practical use for this and have come up empty. I know there are examples of such a thing, but do people really make use of this in their scripts? I feel like it figuring out how to avoid it would be more common than using it as a feature.
Shadow Thief
Posts: 12
Joined: 2021-Aug-03, 1:45 am

Re: Are there any scripts that DEPEND on NOT using Delayed Expansion?

Post by Shadow Thief »

The only time you really need to disable delayed expansion is when you're working with filenames that contain exclamation points.
Rekrul
Posts: 52
Joined: 2021-Aug-15, 11:29 pm

Re: Are there any scripts that DEPEND on NOT using Delayed Expansion?

Post by Rekrul »

Shadow Thief wrote: 2023-Mar-08, 4:32 am The only time you really need to disable delayed expansion is when you're working with filenames that contain exclamation points.
Yes, but since you never know ahead of time whether a filename will contain an exclamation point, leaving Delayed Expansion on all the time can cause any script that deals with files to fail unexpectedly.

Personally, i think the Microsoft developers really dropped the ball with Delayed Expansion. I mean, why did they tie the commands to enable and disable it it to the Local commands? Why can't you just just enable and disable it where you want, without having to use a SetLocal command? For that matter, why did they make it a command at all? Why not just have %variable% act the way it always did, and !variable! always be expanded? Wouldn't that have made a lot more sense than adding a kludge that forces users to use special variable notation anyway?

And why does Delayed Expansion make it impossible to use exclamation points in variables? Both exclamation points and percent signs are used to mark variables, but you can use percent signs in variables, so why are exclamation points off limits?

For that matter why is turning ON variable expansion referred to as enabling Delayed Expansion? When a variable is in a loop, its value can't be read until the loop has ended. Isn't that delaying the expansion? The literal definition of the words enabling Delayed Expansion means to expand later, which is the exact opposite of what it actually does. The entire thing is ass-backwards.
Shadow Thief
Posts: 12
Joined: 2021-Aug-03, 1:45 am

Re: Are there any scripts that DEPEND on NOT using Delayed Expansion?

Post by Shadow Thief »

If you think you might encounter a filename that contains an exclamation point, then disable it. Thankfully, most normal people don't put exclamation points in their filenames unless they're working with ROMs or something, so it's largely a non-issue.

The number one goal of Microsoft's work with batch scripts is backwards compatibility, so you can't just turn features on by default in case the user actually needs the literal string !variable! to be displayed for some reason. Exclamation points aren't off limits in variable values, they just need to be escaped the same way that percent signs are (you can't say set "half=50%" for example, you have to say set "half=50%%" since the percent sign needs to be escaped).

And you're not turning variable expansion on; it was already on. It's always on. Your terminology is wrong and you're confusing yourself. "Variable expansion" is when a variable is replaced with its value. By default, this happens when the line is read by the interpreter. When you enable delayed expansion, the replacement doesn't happen until the line is executed. It may feel like these two things happen pretty much at the same time, but they're actually fairly far apart in the order of execution. You can read more about that here: https://stackoverflow.com/questions/409 ... se-scripts
Rekrul
Posts: 52
Joined: 2021-Aug-15, 11:29 pm

Re: Are there any scripts that DEPEND on NOT using Delayed Expansion?

Post by Rekrul »

Shadow Thief wrote: 2023-Mar-13, 6:33 am If you think you might encounter a filename that contains an exclamation point, then disable it. Thankfully, most normal people don't put exclamation points in their filenames unless they're working with ROMs or something, so it's largely a non-issue.
Sometimes I use exclamation points to cause those files to be sorted to the top of a list.
Shadow Thief wrote: 2023-Mar-13, 6:33 am The number one goal of Microsoft's work with batch scripts is backwards compatibility
How do you reconcile that statement with the fact that they completely omitted the Choice command from Windows XP/NT/2003? Yes, it was available as part of a resource kit, but not everyone is going to have that. Plus there's the fact that the syntax of the choice command changed between XP and Vista, such that a choice command written for use on XP won't work at all on Vista+, and vice-versa.

There's also the fact that under DOS, you could change the foreground and background colors for individual pieces of text, but the Windows cmd window only allows one foreground and one background color per window.
Shadow Thief wrote: 2023-Mar-13, 6:33 am so you can't just turn features on by default in case the user actually needs the literal string !variable! to be displayed for some reason.
OK, but why are you forced to use a SetLocal command to enable Delayed Expansion? Wouldn't it have made more sense to make EnableDelayedExpansion and DisableDelayedExpansion stand-alone commands?
Shadow Thief wrote: 2023-Mar-13, 6:33 am Exclamation points aren't off limits in variable values, they just need to be escaped the same way that percent signs are (you can't say set "half=50%" for example, you have to say set "half=50%%" since the percent sign needs to be escaped).
I can't figure out how to escape it in a set command. This doesn't work;

Code: Select all

set test=hello^!
Nor does doubling the exclamation point, or doubling the caret, or anything else that I tried. Additionally, if the variable is defined before Delayed Expansion is turned on, and then you perform any operation on that variable, any exclamation points will be stripped out of it.

The upshot being that when Delayed Expansion is enabled, trying to use exclamation points for anything is a colossal pain in the ass, much more so than the percent sign.
OJBakker
Posts: 13
Joined: 2021-Jul-29, 7:06 am

Re: Are there any scripts that DEPEND on NOT using Delayed Expansion?

Post by OJBakker »

Try this:

Code: Select all

@echo off
setlocal disabledelayedexpansion
echo disabled delayedexpansion

set test=hello!
set test

set "test=hello!"
set test

endlocal

setlocal enabledelayedexpansion
echo enabled delayedexpansion

set test=hello!
set test

set "test=hello!"
set test

set "test=hello^!"
set test

set test=hello^!
set test

set test=hello^^!
set test

endlocal

pause
Shadow Thief
Posts: 12
Joined: 2021-Aug-03, 1:45 am

Re: Are there any scripts that DEPEND on NOT using Delayed Expansion?

Post by Shadow Thief »

Rekrul wrote: 2023-Mar-15, 3:28 am
Shadow Thief wrote: 2023-Mar-13, 6:33 am If you think you might encounter a filename that contains an exclamation point, then disable it. Thankfully, most normal people don't put exclamation points in their filenames unless they're working with ROMs or something, so it's largely a non-issue.
Sometimes I use exclamation points to cause those files to be sorted to the top of a list.
Use an underscore instead.
Rekrul wrote: 2023-Mar-15, 3:28 am
Shadow Thief wrote: 2023-Mar-13, 6:33 am The number one goal of Microsoft's work with batch scripts is backwards compatibility
How do you reconcile that statement with the fact that they completely omitted the Choice command from Windows XP/NT/2003? Yes, it was available as part of a resource kit, but not everyone is going to have that. Plus there's the fact that the syntax of the choice command changed between XP and Vista, such that a choice command written for use on XP won't work at all on Vista+, and vice-versa.

There's also the fact that under DOS, you could change the foreground and background colors for individual pieces of text, but the Windows cmd window only allows one foreground and one background color per window.
Choice is an executable, not a command. Refer to https://ss64.com/nt/choice.html
VT100 escape sequences have been enabled since Windows 10. I highly recommend that you update your computer and then read https://learn.microsoft.com/en-us/windo ... -sequences
Rekrul wrote: 2023-Mar-15, 3:28 am
Shadow Thief wrote: 2023-Mar-13, 6:33 am so you can't just turn features on by default in case the user actually needs the literal string !variable! to be displayed for some reason.
OK, but why are you forced to use a SetLocal command to enable Delayed Expansion? Wouldn't it have made more sense to make EnableDelayedExpansion and DisableDelayedExpansion stand-alone commands?
No, you're updating the behavior of the environment, so you need setlocal to instantiate a new instance of the environment.
Rekrul wrote: 2023-Mar-15, 3:28 am
Shadow Thief wrote: 2023-Mar-13, 6:33 am Exclamation points aren't off limits in variable values, they just need to be escaped the same way that percent signs are (you can't say set "half=50%" for example, you have to say set "half=50%%" since the percent sign needs to be escaped).
I can't figure out how to escape it in a set command. This doesn't work;

Code: Select all

set test=hello^!
Nor does doubling the exclamation point, or doubling the caret, or anything else that I tried. Additionally, if the variable is defined before Delayed Expansion is turned on, and then you perform any operation on that variable, any exclamation points will be stripped out of it.

The upshot being that when Delayed Expansion is enabled, trying to use exclamation points for anything is a colossal pain in the ass, much more so than the percent sign.
Use exclamation points around variables when you're using delayed expansion. Here are four different ways to print the string "hello!":

Code: Select all

@echo off
setlocal enabledelayedexpansion

REM These are the "correct" way to do it
set test[0]=hello^^!
echo !test[0]!

set "test[1]=hello^!"
echo !test[1]!

REM These also work, but people don't do them for reasons that should be obvious
set test[2]=hello^^^^^^^^^^!
echo %test[2]%

set "test[3]=hello^^^^^!"
echo %test[3]%
It makes more sense the more you do it, so keep practicing. When in doubt, add more ^s until it works.
Post Reply