1

How to avoid delayed expansion removing the exclamation marks in file names?

@echo off

Set path="C:\example"
Set chars=a b c

cd /d %path%

setlocal EnableDelayedExpansion
for %%A in (%chars%) do (
    set filesList=
    for /F "tokens=* delims=" %%B in ('dir %%A^* /a-d /b') do (
        set filesList=!filesList!"%%~nxB"
    )
    if not "!filesList!"=="" (
        echo %%A filesList: !filesList!
    )
)
endlocal
Mofi
  • 38,783
  • 14
  • 62
  • 115
  • 1
    First, please read [What is the reason for '...' is not recognized as an internal or external command, operable program or batch file?](https://stackoverflow.com/a/41461002/3074564) The environment variable `PATH` is a __very, very__ important predefined environment variable. Replacing the value of this predefined environment variable by something like `"C:\example"` is really no good idea. – Mofi Jun 05 '18 at 06:01
  • Second, read next answers on [Why is no string output with 'echo %var%' after using 'set var = text' on command line?](https://stackoverflow.com/a/26388460/3074564) and [How to set environment variables with spaces?](https://stackoverflow.com/a/34402887/3074564) to learn the important difference between `set MyPath="C:\example"` and `set "MyPath=C:\example"`, i.e. position of first double quote. And use `cd /D "%MyPath%"` once knowing the important difference. – Mofi Jun 05 '18 at 06:04
  • Third, `tokens=*` and `delims=` have both the same effect, disable line splitting into substrings. It would be better to use `"eol=| delims="` instead of `"tokens=* delims="` to disable line splitting and additionally process also file names starting with a semicolon. Fourth, the asterisk `*` must not be escaped with `^` in __FOR__ command line. It has no special meaning for `cmd.exe` itself processing the batch file. – Mofi Jun 05 '18 at 06:09
  • Fifth, you can use `call set filesList=%%filesList%%"%%~nxB"`, `if defined filesList` and `call echo %%A filesList: %%filesList%%` to avoid usage of delayed expansion. – Mofi Jun 05 '18 at 06:13
  • @Squashman Thank you :) @Mofi For first: Thanks, I learned new things about PATH, actually I did use the name `"DirWithFiles"` but in the hurry to change it for this question I didn't thought that I was using PATH lol. For second: difference learned thx, using `set "MyPath=C:\example"` and `cd /D "%MyPath%"` now. For third:so `|` means new line or carriage return rt? For fourth: removed and working ty. For Fifth:cool Thanks it worked!. For PS: ok will do, Thank you and good luck to you too :). – Mr. Sr. J. Doe Jun 06 '18 at 01:31
  • @MrSrJDoe `eol=|` replaces default `eol=;`. The default results in lines starting with `;` being ignored by __FOR__. `dir %%A* /a-d /b` outputs file names line by line. A file name can start with a semicolon. Therefore file names starting with `;` would be ignored by __FOR__. `eol=|` redefines end of line character to vertical bar character. File/folder names cannot contain `|` (redirection operator). That is not possible on Windows. So no file name ignored anymore by __FOR__. Well, your code processes files matching `a*`, `b*`, `c*` and so no processed file name starts ever with a semicolon. – Mofi Jun 06 '18 at 05:05

1 Answers1

1

As Mofi suggested, you could disable delayed expansion and use

call set filesList=%%filesList%%"%%~nxB"

But that fails when there are carets in your filenames.

The problem in your code is the fact, that FOR parameters can only be safely expanded without delayed expansion mode.
Normally you use the toggline technic for this, like here.

setlocal DisableDelayedExpansion
for /F "delims=" %%B in ('dir %%A^* /a-d /b') do  ( 
    set "line=%%B"

    setlocal EnableDelayedExpansion
    REM *** Process the content of line here
    echo !line!
    endlocal
)

But this only works, when you don't need to transfer the content of line out of the (inner) setlocal scope.

In your case, you tried to add the line content to a filesList variable outside of the scope. For this case you need to transfer the content of line over the scope end with a more or less complex technic, like
Make an environment variable survive ENDLOCAL
Macro to return multiple variables across endlocal barriers

jeb
  • 70,992
  • 15
  • 159
  • 202
  • you're rt files with carets gets double carets, and you're rt too about the toggline techinc (tried it), for now the files I work with only have exclamation marks, but if I find many with carets i'll try return.bat. Thank you all, you're really helpful, good luck! – Mr. Sr. J. Doe Jun 06 '18 at 01:31