Another option is to escape any !
and ^
that may exist in the listing before it is processed by the FOR /F loop. That would be difficult and slow using pure batch. But it is simple and fast if you use a hybrid JScript/batch utility called REPL.BAT that can perform a regex search and replace on stdin and write the result to stdout. The utility is pure script that will run on any Windows machine from XP onward.
Assuming that REPL.BAT is in your current directory, or better yet, somewhere within your path:
@echo off
setlocal enabledelayedexpansion
for /f "eol=: delims=" %%a in ('dir /b *.txt^|repl "\^^|^!" "^^$&"') do (
set "file=%%a"!
set /a count+=1
echo !count!:!file!
)
File names could contain !
and/or ^
. The ^
must also be escaped if the command line also contains !
. Rather than determine if !
exists, I blindly escape both ^
and !
, and then append an extra !
in the SET statement. The trailing !
triggers the ^
escape processing properly, but it appears after the last "
, so it is ignored by the SET command.
Note that "tokens=* delims="
is redundant in the original post. Also, a file name could begin with ;
, in which case the implicit EOL=;
would cause that file to be skipped. But a file name cannot begin with :
, So I used "eol=: delims="
instead.
My code works just fine. But given the OP's exact task, I would opt to use the Magoo solution instead. The MC ND solution is also good. They are simpler than my solution.
However, it is easy to extend the problem such that neither the Magoo or MC ND solution work. Suppose additional variable manipulation must be done within the loop that requires delayed expansion, and the result of those manipulations must be preserved. For example, you might want to build a comma delimited list of values in a single variable. This is not a great example because the list could exceed the maximum variable length of 8191 bytes. But it serves to illustrate the problem.
There is specialized code to transport variable values accross the ENDLOCAL barrier. But that code is tricky, and also can slow down the loop considerably.
The REPL.BAT solution is very simple, fast, and convenient.
@echo off
setlocal enableDelayedExpansion
set "list="
set "cnt=0"
for /f "delims=" %%A in ('dir /b *.txt^|repl "\^^|^!" "^^$&"') do (
set /a cnt+=1
set "list=!list!, !cnt!:"%%A""
)
set "list=!list:~2!"
echo list=!list!