3

I got two txt files "test-exclamations!!!.txt", "test-normal.txt" and a bat file contains the script below in the same folder.

ECHO OFF & CLS
SETLOCAL ENABLEDELAYEDEXPANSION

FOR /F "tokens=* delims=" %%a IN ('dir /b *.txt') DO (
    set /a count=count+1
    echo !count!:%%a
)

ENDLOCAL
EXIT/B

and I get the result:

1:test-exclamations.txt
2:test-normal.txt

We can see the exclamation marks disappeared.
I've got some method to keep the exclamation marks from the Internet, but I cannot keep both the exclamation marks and the value of variable "count".

Please tell me how to keep the both.

mts
  • 109
  • 2
  • 3
  • 10

3 Answers3

4
@ECHO OFF
    setlocal enableextensions disabledelayedexpansion

    FOR /F "tokens=* delims=" %%a IN ('dir /b *.txt') DO (
        set /a "count+=1"
        set "file=%%a"
        setlocal enabledelayedexpansion
        echo !count!:!file!
        endlocal
    )

    endlocal
MC ND
  • 69,615
  • 8
  • 84
  • 126
1
dir /b test-*.txt|findstr /n "^"

will achieve the result you indicatein deayed-expansion mode.

Magoo
  • 77,302
  • 8
  • 62
  • 84
1

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!
Community
  • 1
  • 1
dbenham
  • 127,446
  • 28
  • 251
  • 390
  • Thank you all the same, but I need that just with pure batch, ^_^ – mts Dec 21 '13 at 12:55
  • @mts - Because it is an assignment that stipulates pure batch? Unless standard JSCRIPT (or the CSCRIPT engine) is somehow disabled on your machine, then the hybrid approach will work on absolutely any Windows machine from XP onward. – dbenham Dec 21 '13 at 13:04