DELAYEDEXPANSION and exclamations

M

Michael Herz

Hi all,

If I'm running a "FOR /R" loop that encounters a directory with an
exclamation in it's name and DELAYEDEXPANSION is on, it fails because the
exclamation is left out of the command that FOR builds. The following code
will demonstrate this if you run it on a dir that has a subdir with an ! in
it's name:

setlocal enabledelayedexpansion
for /r "%~1" %%a in (.) do (
dir "%%a">nul
)
endlocal

You will see a "The system cannot find the file specified." pop up.

Any thoughts would be appreciated.
 
J

Jerold Schulman

Hi all,

If I'm running a "FOR /R" loop that encounters a directory with an
exclamation in it's name and DELAYEDEXPANSION is on, it fails because the
exclamation is left out of the command that FOR builds. The following code
will demonstrate this if you run it on a dir that has a subdir with an ! in
it's name:

setlocal enabledelayedexpansion
for /r "%~1" %%a in (.) do (
dir "%%a">nul
)
endlocal

You will see a "The system cannot find the file specified." pop up.

Any thoughts would be appreciated.

If the folder was C:\\Exc!mark

use C:\\Exc^^!mark

Jerold Schulman
Windows: General MVP
JSI, Inc.
http://www.jsiinc.com
 
M

Matthias Tacke

Michael Herz said:
Hi all,

If I'm running a "FOR /R" loop that encounters a directory with an
exclamation in it's name and DELAYEDEXPANSION is on, it fails because the
exclamation is left out of the command that FOR builds. The following code
will demonstrate this if you run it on a dir that has a subdir with an ! in
it's name:

setlocal enabledelayedexpansion
for /r "%~1" %%a in (.) do (
dir "%%a">nul
)
endlocal

You will see a "The system cannot find the file specified." pop up.

Any thoughts would be appreciated.
Beside avoiding either exclamation marks or enabledelayedexpansion
(or temporarily switching to disabledelayedexpansion) I see no cure for
your problem.

The for variable passes a value without exclamation mark when delayed
exp. is enabled - and if a folder with that name exists its the wrong
one.

setlocal enabledelayedexpansion
for /r "%~1" %%a in (.) do (dir "%%a">nul)
setlocal disabledelayedexpansion
for /r "%~1" %%a in (.) do (dir "%%a">nul)
endlocal


HTH
 
M

Michael Herz

Exclamations really should have been in the list of disallowed characters
for file names :-(

I thought about scanning for !s and possibly replacing with ^^!s but that's
a lot of work if it's doable at all.

Mike
 
M

Michael Herz

Jerold Schulman said:
If the folder was C:\\Exc!mark

use C:\\Exc^^!mark

The problem is that "FOR /F" is going to be filling in the data based on
what it finds in your dir tree. It's not a user entry.
 
M

Matthias Tacke

Michael Herz said:
Exclamations really should have been in the list of disallowed characters
for file names :-(

I thought about scanning for !s and possibly replacing with ^^!s but that's
a lot of work if it's doable at all.

Mike

Not a lot of work, but I'd replace with a minus. But if programs with
registry entries rely on the exclamation mark there is a problem.

@echo off
setlocal disabledelayedexpansion
for /F "delims=" %%A in ('dir /S/B \*!*') do (
set new=%%A
call set new=%%new:!=-%%
call echo ren "%%A" %%new%%
rem call echo ren "%%A" %%new%% >>renexclam.cmd
)

But I'd edit renexclam.cmd before executing it. There are some files
(like PLUS!.hlp in w98) which should keep their names.
 
M

Michael Herz

Thanks Matthias but that's not what I meant. I meant that I thought about
catching the offending files while in the enabledelayedexpansion FOR loop
and somehow specially handling them there.

This limitation almost makes any cmd script that uses "FOR /F" unusable.

Mike
 
M

Matthias Tacke

Michael Herz said:
Thanks Matthias but that's not what I meant. I meant that I thought about
catching the offending files while in the enabledelayedexpansion FOR loop
and somehow specially handling them there.

This limitation almost makes any cmd script that uses "FOR /F" unusable.

Mike
You realized, that my batch uses some tricks to circumvent the usage of
enabledelayedexpansion? This way your batches also stay compatible with
win nt4 which doesn't know of delayedexpansion at the cost of slower
execution when using additional calls.

You may also call internal subs, so I can't fully agree with your
statement. For /f is still one of the most useful and used enhanced
commands.
 
M

Michael Herz

The reason that I say this limitation almost makes any cmd script that uses
"FOR /F" unusable is because if you run into a directory with an ! in it's
name, the for loop will process the dir with the name minus the !. Hopefully
you have error proofed your code so you handle "file not found" errors
properly but in a bad case, processing could pass to an unintended
directory. For example, files in a "!windows" dir would process directing
the commands to the "windows" dir. Depending on what you are doing, this
could be catastrophic.
 
A

Al Dunbar [MS-MVP]

Michael Herz said:
The reason that I say this limitation almost makes any cmd script that uses
"FOR /F" unusable is because if you run into a directory with an ! in it's
name, the for loop will process the dir with the name minus the !. Hopefully
you have error proofed your code so you handle "file not found" errors
properly but in a bad case, processing could pass to an unintended
directory. For example, files in a "!windows" dir would process directing
the commands to the "windows" dir. Depending on what you are doing, this
could be catastrophic.

The factors you describe are a good reason to do either or both of the
following:

- develop a standard file and folder naming convention that avoids
problematic filename characters such as "!", "(", and ")".

- test all batch code using the most obtuse file names allowed by the above
policy, and consider using vbscript or some other less syntactically
limiting language when your find most of your coding time is dealing with
filename issues.

Given the above, I use FOR /F in a large proportion of my batch scripts, and
find that it works flawlessly.


/Al
 
M

Michael Herz

Al Dunbar said:
The factors you describe are a good reason to do either or both of the
following:

- develop a standard file and folder naming convention that avoids
problematic filename characters such as "!", "(", and ")".

- test all batch code using the most obtuse file names allowed by the above
policy, and consider using vbscript or some other less syntactically
limiting language when your find most of your coding time is dealing with
filename issues.

Given the above, I use FOR /F in a large proportion of my batch scripts, and
find that it works flawlessly.


/Al

I couldn't agree with you more. I too have had great success with cmd.exe.
I've managed to avoid "(", and ")" problems by rigorously following quote
around filename rules however I've been stumped by "!"s

Unfortunately I have to manage systems where other's are in control of
filenames so I don't have the luxury of forbidding "!"s. I wish MS had done
that as it's core to cmd.exe ;-)

Mike
 
G

guard

Michael Herz said:
I couldn't agree with you more. I too have had great success with cmd.exe.
I've managed to avoid "(", and ")" problems by rigorously following quote
around filename rules however I've been stumped by "!"s

Unfortunately I have to manage systems where other's are in control of
filenames so I don't have the luxury of forbidding "!"s. I wish MS had done
that as it's core to cmd.exe ;-)

Mike

The .Mount/\Command ".ForExpand" will expand variables
at execution time, providing the same functionality as
"Delayed Expansion", without the hassle.

ForExpand works CONSISTENTLY under NT/2K/XP/K3 using the syntax

%.ForExpand% %%A IN ('SET VariableName') DO (Command %%B)

%%A = VariableName
%%B = Dynamically calculated CONTENTS of VariableName

For a color-keyed example, see
(http://TheSystemGuard.com/MtCmds/CrystalClear/ForExpand.htm)

ForExpand is part of the (FREE) Advanced Command Library.
(http://ntlib.com)

When running scripts on systems you don't administer, the Advanced
NT/2K/XP/K3 Command Library fully supports loading across the network from a
Read-Only share point. For example:

CALL \\MachineThatYouDOControl\share\ntlib.cmd /Init /Quiet

*******

This thread has highlighted just one of the reasons that DelayedExpansion is
a "hassle". There were already enough "Syntax Ditches" to cross when
writing shell scripts without adding another layer of complexity with
"!variable!".

Enhanced functionality does NOT have to be more complex. Command Libraries
provide hundreds of additional resources in a self-documenting,
cross-compatible format. This reduces the complexity of the code while
allowing the less experienced administrator to solve complicated problems
using only a "batch file". Most importantly, he or she can actually
UNDERSTAND (!) what is going on.

Remember, shell scripting is the one area of "programming" where many
non-programmers are tasked with "writing a little batch file" when they have
only minimal exposure to a "C:\>" prompt and it's capabilities.

*******

-tsg

/-----------------+---------------+----------------------\
| COMPATIBILITY | CLARITY | SPEED |
| Write code ONCE | Make it clear | THEN...Make it fast! |
\-----------------+---------------+----------------------/
400+ command-line resources using ONLY native NT commands!
(http://TheSystemGuard.com/default.asp#MasterCommandList)
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top