Exclamation Point Escaping after Dir Command in FOR-Loop for File Processing

Cumbrowski
Cumbrowski used Ask the Experts™
on
The Example Code below performs a DIR command for the specified folder and uses the FOR /F loop to break up the results, passing one file name after another to the processing function :perfaction.


The :perfaction in my example simply returns the file name via ECHO and attempt to display its content via the TYPE command.


The code works well in almost any case, but if the file name contains either an exclamation mark (!) or the caret character (^)
The Exclamation Mark is simply suppressed.


The file
"C:\SOME FOLDER\SOME WHERE\--!--ExclamationMark.txt" is being returned by the first FOR Loop as
"C:\SOME FOLDER\SOME WHERE\----ExclamationMark.txt"

and the file
"C:\SOME FOLDER\SOME WHERE\--^--caret.txt" is being returned as
"C:\SOME FOLDER\SOME WHERE\--^^--caret.txt"

In Both examples returns the IF EXIST statement in the Original Code "No", because it is unable to find the files.


I was able to find an ugly workaround for the caret problem, which I also included below as example #2
I was not able to solve the problem with the exclamation mark though.


@ECHO OFF
REM ---------------------------------------------
REM Example #1 Original Code
REM ---------------------------------------------
SETLOCAL EnableDelayedExpansion
CLS
SET Folder=C:\SOME FOLDER\SOME WHERE
FOR /f "tokens=*" %%a IN ('DIR /s /a-d /on /b "%Folder%"') DO CALL :perfaction "%%a%"
GOTO :EOF
 
 
:perfaction
SET FName="%~f1"
ECHO %FName%
If EXIST %FName% (
  ECHO Yes
  TYPE %FName%
) else (
  ECHO No
)
ECHO.
GOTO :EOF
 
--------------------------------------------------------------------------------------
 
 
@ECHO OFF
REM ---------------------------------------------
REM Example #2 Caret Workaround
REM ---------------------------------------------
SETLOCAL EnableDelayedExpansion
CLS
SET Folder=C:\SOME FOLDER\SOME WHERE
FOR /f "tokens=*" %%a IN ('DIR /s /a-d /on /b "%Folder%"') DO CALL :perfaction "%%a%"
GOTO :EOF
 
 
:perfaction
Set FName="%~f1"
SET FName=!FName:^^^^=^^!
Echo !FName!
If EXIST !FName! (
  ECHO Yes
  TYPE !FName!
) else (
  ECHO No
)
ECHO.
GOTO :EOF

Open in new window

Comment
Watch Question

Do more with

Expert Office
EXPERT OFFICE® is a registered trademark of EXPERTS EXCHANGE®
Most Valuable Expert 2018
Distinguished Expert 2018

Commented:
Try the second version again, remove the "EnableDelayedExpansion", and change the variable expansion back to % from !; there's no need for delayed expansion in this case.
@ECHO OFF
REM ---------------------------------------------
REM Example #2 Caret Workaround
REM ---------------------------------------------
SETLOCAL
CLS
SET Folder=C:\SOME FOLDER\SOME WHERE
FOR /f "tokens=*" %%a IN ('DIR /s /a-d /on /b "%Folder%"') DO CALL :perfaction "%%a%"
GOTO :EOF
 
 
:perfaction
Set FName="%~f1"
SET FName=%FName:^^^^=^^%
Echo %FName%
If EXIST %FName% (
  ECHO Yes
  TYPE %FName%
) else (
  ECHO No
)
ECHO.
GOTO :EOF

Open in new window

Qlemo"Batchelor", Developer and EE Topic Advisor
Top Expert 2015

Commented:
If you change it to the following syntax, the caret workaround is not needed. (And there has been a superflous % at the end of the FOR variable).

@ECHO OFF
REM ---------------------------------------------
REM Example #1 Original Code
REM ---------------------------------------------
setlocal DisableDelayedExpansion
CLS
SET Folder=C:\SOME FOLDER\SOME WHERE
FOR /f "tokens=*" %%a IN ('DIR /s /a-d /on /b "%Folder%"') DO call :perfaction "%%a"
GOTO :EOF
 
 
:perfaction
SET "FName=%~f1"
ECHO %~f1 %FName%
If EXIST %FName% (
  ECHO Yes
  TYPE %FName%
) else (
  ECHO No
)
ECHO.
GOTO :EOF

Open in new window

Commented:
You need to be careful with your double-quotes to do that. Here's the solution:
.
:
@ECHO OFF
CLS
FOR /f "tokens=*" %%a IN ('DIR /s /a-d /on /b "c:\some folder\some where\.*"') DO CALL :perfaction "%%a"
GOTO :EOF
 
 
:perfaction
SET FName=%~dp1%~nx1
ECHO "%FName%"
If EXIST "%FName%" (
  ECHO Yes
  TYPE "%FName%"
) ELSE (
  ECHO No
)
ECHO.
:

Open in new window

CompTIA Cloud+

The CompTIA Cloud+ Basic training course will teach you about cloud concepts and models, data storage, networking, and network infrastructure.

Commented:
Oops! Just discovered a typing error - sorry:

You need to be careful with your double-quotes to do that. Here's the solution:
:
:
@ECHO OFF
CLS
FOR /f "tokens=*" %%a IN ('DIR /s /a-d /on /b "c:\some folder\some where\*.txt"') DO CALL :perfaction "%%a"
GOTO :EOF
 
 
:perfaction
SET FName=%~dp1%~nx1
ECHO "%FName%"
If EXIST "%FName%" (
  ECHO Yes
  TYPE "%FName%"
) ELSE (
  ECHO No
)
ECHO.
:

Open in new window

Commented:
You could also use this under most circumstances if you're looking at files in the current folder:
:
:
@ECHO OFF
CLS
FOR %%a IN (*.txt) DO CALL :perfaction "%%a"
GOTO :EOF
 
 
:perfaction
SET FName=%~dp1%~nx1
ECHO "%FName%"
If EXIST "%FName%" (
  ECHO Yes
  TYPE "%FName%"
) ELSE (
  ECHO No
)
ECHO.
:

Open in new window

Commented:
Note that this will work too:

   SET FName=%~dpnx1
Commented:
Final code (for speed, it's best to be specific about filespec: *.txt):


@ECHO OFF
CLS
FOR /f "tokens=*" %%a IN ('DIR /s /a-d /on /b "c:\some folder\some where\*.txt"') DO (
   CALL :perfaction "%%a"
)
EXIT /B
 
 
:perfaction
SET FName=%~dpnx1
ECHO "%FName%"
If EXIST "%FName%" (
  ECHO Yes
  TYPE "%FName%"
) ELSE (
  ECHO No
)
ECHO.

Author

Commented:
Uhm... So the "SETLOCAL EnableDelayedExpansion" changes this behavior.
This example is only a simplified and generalized version of various scripts that do something with files and/or folders.
Some of them require the use of Delayed Expansion (E.g. counters and stuff).

Correct me, if I am wrong, but you can enable and disable delayed expansion in a script to localize it to only those sections where it is needed, right? Like this (simplified version without Calls of any batch labels):

Script Start

... some code without DE ...

SETLOCAL EnableDelayedExpansion
 ... some code with DE ...
ENDLOCAL

... some code without DE ...

End Script

Commented:
SETLOCAL alone does not effect the filenames

Only the ENABLEDELAYEDEXPANSION part does. It effects the exclamation marks in filenames.

You can dynamically set and end localisation of delayed expansion however, while delayed variables (!...!) inside delayed expansion blocks are expanded at execution time, immediate variables (%...%) are expanded at parse time. Conversely, both delayed and Immediate variables outside delayed expansion blocks are expanded at parse time.

Why don't you describe what it is you are trying to do as I may be able to suggest a better way (and quite possibly, a correct way) of doing it.

Commented:
You must realise that sometimes the ONLY way you can achieve something is with the use of either '%%x' and '%x' type variables.

That means, sometimes you may have to CALL a subroutine purely to convert from a standard variable, be it immediate or delayed, into a command line parameter.

Another way to convert to a FOR-type variable is:

   FOR %%a IN ("%variable%") DO (
      REM %%a is now the value of %variable%
   )

But none of this is of any real help to you in making your code work without the use of CALL because FName would be a dynamic variable inside a FOR body and would require delayed expansion. The problem with this then is that the delayed variable delimiters (!...!) cancel out the exclamation marks in the variable.

I provided you with a solution to your example code above in comment ID: 24888245. There is absolutely nothing wrong in using this approach in your code.



Qlemo"Batchelor", Developer and EE Topic Advisor
Top Expert 2015

Commented:
setlocal in any form has the disadvantage to not only change the Delayed Expansion behaviour, but keep environment variable changes local. For switching the behaviour and get changes exported, you have to do code like
 
 setlocal EnableDelayedExpansion
set i=1
set a1=2
set x=!a%i%!
setlocal DisableDelayedExpansion & set x=%x%
REM %x% can be used here.
...

The same is valid for temporary switching off of DE.

t0t0,
ID 24888245 does not work with Delayed Expansion. Why should that code be favoured over the other posts? %~dpnx1 is the same as %~f1.

 

Commented:
Qlemo....

FIRSTLY, to asnwer your question: Because even by removing the delayed expansion the asker's code STILL DOES NOT WORK - so, that was NOT the real issue here. However, if you care to take a CLOSER look at my code which DOES WORK, you will find line-by-line subtle, YET VITAL changes, that now make the asker's code WORK PERFECTLY.

Now, If the asker wishes to retain delayed expansion and still have his code work perfectly then I can do that too (CalmSoul - Please advise).

The asker has included code in his question which clearly DOES NOT work. Even when delayed expansion is removed it does not work.

I have edited the asker's code in my comment (ID 24888245) and now it DOES work.

There is NO NEED to delay expansion in his code furthermore, I have drawnd the asker's attention to his use of double-quotes in an earlier comment (ID: 24888223).

As far as I'm concerned, the question has been answered.


As for the %~f1 and %~dpnx1, it's basically the same thing so that's neither here nor there.

The problem here is deeper than you attempt to depict with your example code and therefore it is not relevent in what the asker is trying to accomplish.
Qlemo"Batchelor", Developer and EE Topic Advisor
Top Expert 2015

Commented:
t0t0,
your code DOES NOT WORK if Delayed Expansion is active (which can be done by cmd /v:on, or registry setting, or from a calling batch file ...). It is clearly stated that DE is needed on other places in the batch file.

You made a point about the quotes - that much is absolutely true. Neither oBdA's nor mine code do honour that correctly, what will result in syntax errors with file names containing spaces. The examples did not contain spaces, however.

So in fact our codes have to merged together and integrated accordingly in the more complicated batch file the poster wants to use (but didn't provide yet).
Most Valuable Expert 2018
Distinguished Expert 2018

Commented:
t0t0,
by removing the quotes around "%~f1", your "perfectly working" code now chokes on file names that contain an ampersand, which could be handled before.
In fact, on closer inspection, every code here based on <call :bla "%%a"> will choke on file names containing percent signs.
There are several issues here, resulting from delayed expansion and the method to call the subroutine.
When using
call :bla "%%a"
a single caret will be replaced in the call by a double caret, which is supposed to escape the original caret when expanding the argument:
set FName=%~1
This assignment will fail, though, if %1 contains an ampersand, because everything after the ampersand will be interpreted as a command; quotes around the argument will be needed:
set FName="%~1"
This seems to work without quotes only inside of a "for" loop.
To get around the caret problem as well as the percent problem, the FName variable needs to be set already in the "for" loop.
Exclamation marks are totally incompatible with delayed expansion.
The following code should be able to handle carets, ampersands, percent signs, and exclamation marks, while keeping delayed expansion for the main program.
Note that each "setlocal" should have a matching "endlocal"; "setlocal" has a maximum recursion depth of 32.
@echo off
cls
setlocal enabledelayedexpansion
set Folder=C:\SOME FOLDER\SOME WHERE
setlocal disabledelayedexpansion
FOR /f "tokens=*" %%a IN ('DIR /s /a-d /on /b "%Folder%"') DO (
  set FName=%%a
  call :perfaction
)
endlocal
goto :eof
 
:perfaction
echo "%FName%"
if exist "%FName%" (
  echo Yes
  type "%FName%"
) else (
  echo No
)
echo.
goto :eof

Open in new window

Commented:
Qlemo.... I agree my code does not work if you enable delayed expansion however, delayed expansion is NOT ENABLED by default otherwise, I guess he would not have included it in his code above - Seems fairly obvious, don't you think?

Firstly, nobody mentioned anything about spaces. Secondly, none of the example filenames contain spaces. AND THIRDLY, why don't you run my code with filenames containing spaces before attempting to disprove the integrity of my code. YOU WILL FIND MY CODE WORKS PERFECTLY WELL - EVEN WITH SPACES.

There's no need to merge any codes here as MINE DOES THE JOB QUITE NICELY.

As I said - as far as I'm concerned, this question has been answered. I have taken the asker's code which was NOT working, modified it, and now it WORKS PERFECTLY AS EXPECTED.

I cannot add anymore to this thread at this moment, as anything else would be conjecture and quite possibly irrelevent.

NOTE: Here is my final code again (copied from my earlier comment, and to appease, I have replaced %~dpnx1 with %~f1).


@ECHO OFF
CLS
FOR /f "tokens=*" %%a IN ('DIR /s /a-d /on /b "c:\some folder\some where\*.txt"') DO (
   CALL :perfaction "%%a"
)
EXIT /B
 
 
:perfaction
SET FName=%~f1
ECHO "%FName%"
If EXIST "%FName%" (
  ECHO Yes
  TYPE "%FName%"
) ELSE (
  ECHO No
)
ECHO.
EXIT /B
Qlemo"Batchelor", Developer and EE Topic Advisor
Top Expert 2015

Commented:
t0t0,
please read my post again in repsect to the space thing.

And consider to accept that my code works, too, for the examples given (ignoring the not documented case of filenames containing ampersands, percent signs, spaces).

"PERFECT" is a solution which covers cases not described, but seen as common traps. Like the ampersand.

Commented:
oBdA, >>"by removing the quotes around "%~f1", your "perfectly working" code now chokes on file names that contain an ampersand"

Nobody said anything about ampersands? Ampersands ARE NOT mentioned anywhere in this quastion.

The asker SPECIFICALLY stated he found a work-around to the ceret character problem (albeit a crude one) but not to the exclamation mark problem.

The issue concernig ampersands and percent signs (as well as other special case characters) is an interesting one which may warrant future investigation.

I am aware of the effects on passing special characters with CALL as this was carefully investigated since looking at the question. That is why I was able to give a correct solution to the asker's problem.

Looking at your code, my first observation is you are not passing any command parameters with CALL. In your code, FName is defined as a global variable. Infact, the value in FName is never subjected to any conversion because it is never 'passed' on between different variable types etc.

Also, there is no need to define FOLDER inside a delayed expansion block as there is nothing to expand.

I note you have included an unmatched ENDLOCAL in the main code.

Without passing parameters, I personally prefer the following solution:

@ECHO OFF
CLS
FOR %%a IN ("c:\some folder\some where\*.txt") DO (
  SET FName=%%a
  CALL :perfaction
)
GOTO :EOF
 
:perfaction
ECHO "%FName%"
IF EXIST "%FName%" (
  ECHO Yes
  TYPE "%FName%"
) ELSE (
  ECHO No
)
ECHO.
GOTO :EOF

The main program does not require delayed expansion on this occasion, nor any other occasion.

Commented:
Qlemo, your code does not work with my test data.

Here are the names of my test files:

   --!--exclamation.txt                      contains: "exclamation"
   --!!--twoexclamations.txt             contains: "two exclamations"
   --^--ceret.txt                                contains: "ceret"
   --^^--twoceret.txt                        contains: "two cerets"
   -- -- space.txt                              contains: "spaces"

Please run your code as it appears in your comment ID: 24887894 and verify - it fails on every file.
Most Valuable Expert 2018
Distinguished Expert 2018

Commented:
t0t0,
it's "perfect"ly possible that Cumbrowski didn't mention ampersands "anywhere in this question" because in his original code, ampersands were handled correctly.

No, I am not passing variables because, as I described above, it's the use of the file name as argument for the subroutine that
1. adds the second caret to the argument
2. strips percent signs from the argument

I've already pointed out in the very first post that the script as posted above doesn't require delayed expansion.
Then Cumbrowski stated in http:#a24888716: "This example is only a simplified and generalized version of various scripts that do something with files and/or folders. Some of them require the use of Delayed Expansion (E.g. counters and stuff)."
Surprisingly enough, I'm fully aware that there's no need to use DE to set the Folder variable; I put it there to demonstrate that the use of DE in the main script or other subroutines is possible, while at the same time working with file names containing exclamation marks.
And, no, there is no "unmatched endlocal" in my script. Look again, and you'll find that this "endlocal" closes the "setlocal disabledelayedexpansion" from line 5.
If anything is unmatched, then it's the very first "setlocal enabledelayedexpansion", for which there's no actual need to close it, because it will be closed on script end.

And, yes, it's of course possible to use a simple "for" loop instead of "for /f", provided that Cumbrowski doesn't rely on the sorted output he generates with dir /on. An enumeration with "for" seems to be generating alphabetically sorted output, but I wouldn't rely on it until I see some actual documentation.
And if you're using a simple for loop, it would have to be with /r, because Cumbrowski is recursing through subfolders (dir /s).
@echo off
cls
setlocal enabledelayedexpansion
set Folder=C:\SOME FOLDER\SOME WHERE
set Mask=*.*
setlocal disabledelayedexpansion
FOR /R "%Folder%" %%a IN ("%Mask%") DO (
  set FName=%%a
  call :perfaction
)
endlocal
goto :eof
 
:perfaction
echo "%FName%"
if exist "%FName%" (
  echo Yes
  type "%FName%"
) else (
  echo No
)
echo.
goto :eof

Open in new window

Qlemo"Batchelor", Developer and EE Topic Advisor
Top Expert 2015

Commented:
t0t0,
I did test it, and the only case not working is the file name containing space.

Commented:
Qlemo, I copied and pasted your code as it is and modified the following line (only) so that I can run in my test environment:

   SET Folder=C:\SOME FOLDER\SOME WHERE

changed to:

   SET Folder=--*.txt

and it produces nothing but errors.

I have placed the test files (see above) into the same folder as the batch file.

I'm running this on XP Pro SP3 inside CMD.EXE. Please confirm your system and environment.

I can't understand how you say it works for you when it clearly does not work for me. I'm at a loss and I need to know what is different about your system which makes this work as you say.
Qlemo"Batchelor", Developer and EE Topic Advisor
Top Expert 2015

Commented:
t0t0,
the following, slightly reworked, code works with all your test files, even with spaces, and additionally with ampersands. But some combinations not covered by your examples fail, like
-- %-- space and percent.txt
-- ^-- space and caret.txt

I tested with Vista SP2 and XP SP3.

@ECHO OFF
REM ---------------------------------------------
REM Example #1 Original Code
REM ---------------------------------------------
setlocal DisableDelayedExpansion
CLS
SET Folder=--*
FOR /f "tokens=*" %%a IN ('DIR /s /a-d /on /b "%Folder%"') DO call :perfaction "%%~a"
GOTO :EOF
  
:perfaction
SET "FName=%~f1"
if NOT "%FName: =%" == "%FName%" set FName="%FName%"
set yn= No
if exist %FName% set yn=Yes
ECHO %yn%  %1 	--^>	 %FName%
echo.
if %yn% == No pause
GOTO :EOF

Open in new window

Author

Commented:
Great Knowledge and Help. Also thanks for the additional comments and suggestions to my related questions.

Commented:
Thank you

Author

Commented:
I spent the time to approach the issue from a more scientific point of view.

I created 144 test files

I took the following 24 special characters: ~`!@#$%^&()_-+={}[];',. and SPACE
and created for each the following 6 files for each of those characters (replace [CHAR] with the character)
144 files = 24 characters * 6 test files per character

[CHAR]SomeText
[CHAR][CHAR]SomeText
SomeText[CHAR]
SomeText[CHAR][CHAR]
SomeText[CHAR]SomeText
SomeText[CHAR][CHAR]SomeText

I used a simplified version of the Batch, which I called "testbatch.bat"  that looks as follows:

@ECHO OFF
CLS
Set InpFolder=C:\test\this is a test
FOR /f "tokens=*" %%a IN ('DIR /s /a-d /on /b "%InpFolder%"') DO (
   CALL :perfaction "%%a"
)
EXIT /B
 
:perfaction
SET FName=%~dpnx1
If EXIST "%FName%" (
  ECHO "%FName%" Yes
) ELSE (
  ECHO "%FName%" No
)

I created a second batch file to launch the one above and redirect results and errors to a log file.
I called that batch file "testlaunch.bat" and it contained only the following one line of code:

call testbatch.bat>Log.txt 2>&1

The batch only failed to recognize files with the following pattern
Following file names with character % in the name

[CHAR][CHAR]SomeText
[CHAR]SomeText
SomeText[CHAR][CHAR]
SomeText[CHAR][CHAR]SomeText

Character &
SomeText[CHAR][CHAR]SomeText

The script was aborted entirely when it came across a file name with Character & that had the following pattern
SomeText[CHAR][CHAR]

It worked perfectly fine for all other 138 test files that I created.
I don't know if there is anything that can be done to get around those few limited cases and be able to read and process files or folders with any valid Windows file name. That would be the best, but from what I saw and experienced myself, there does not seem to be a general solution for this problem.

Other batch routines also have to deal with additional special characters like ><|?*"\/ and there is virtually never a solution that is able to deal with all of them. Please proof me wrong on this one. Using a call of a Sub Label does often help to create a work around, but it is also not the every-problem-solving solution either.

I gave t0t0 the full credits for this question, because he answered it to 100%. That this opened up some additional question was not planned. I like the discussion though, because it addresses severe limitation of what you can do with BATCH jobs, but Experts-Exchange is unfortunately not like a forum and the wrong place to have those kind of discussions.

If you Olemo and/or t0t0 would like to take this discussion to a BATCH related forum, let me know and also post a link to it.

Author

Commented:
Olemo

That the script does not work, if you pass a file filter like "--*.txt" was not within the specifications of my question.

I need to be able to read all files (or Folders in some other cases) in a directory (including sub directories) and then process each file or folder via some additional batch code.

t0t0 asked for  specifics about what kind of batches I have in mind. Here are some examples.

Example 1
A script that reads all sub folders in the specified input directory and then jumps into each directory with CD /D DIRPATH to execute a program with command line options there, where the output is redirected to a single text file. Before the program call, after the CD command I also ECHO the full path name to the directory to the same text file, because I need it to be able to associate the results of the tool with the corresponding directory. The tool has basically the limitation that it can only process in the current directory, but I need it to process all subdirectories as well.

Example 2
I wanted to create a batch file that reads all Internet Explorer favorites (.URL files with Sub Folder Structure, usually in C:\Documents & Settings\USERNAME\Favorites) and parses their content (via TYPE).

I wanted to do two things with those.
 1) create a FireFox compatible Bookmarks.HTML file
 2) re-create the .URL Internet Shortcut file without some of the gargabe that is added to it over time by IE

Example 3
Read all files in the folder (maybe with filter, like *.txt or *.html) and concatenate them to a single file.
In some advanced cases did I need to replace some content in the original input file with something else and in other cases did I have to skip some of the lines of the Input file (such as everything before <BODY and after </BODY> for HTML files, where you would create the <html>, <body> and </body>, </html> tags manually via ECHO and only add the BODY section of the HTML to the concatenated file.

Example 4
Read all Files in all directories and sub folders of a specified source directory and move them to a specified destination directory.
If a file already exists (e.g. a file with the same name in another sub folder), check if it has the same size, if it does, skip it, if the size is different, auto rename it by adding [x] to the base name, where x starts with 1 and counts up, until the file name is available in the target directory.

Example 5
Check all Subfolders of a directory and delete the ones that are emty. There I have the code that seems to work properly, at least in all the cases that I came across yet.

REM CleanUp.bat
@echo off
set Folder="%~1"
if %Folder%=="" @echo Syntax CleanUp.bat Folder&goto :EOF
if not exist %Folder% @echo Syntax CleanUp.bat Folder - %Folder% not found.&goto :EOF
setlocal
:: REMOVE EMPTY SUBFOLDERS
for /f "tokens=*" %%A in ('dir /ad /s /b %Folder% ^|Sort /Reverse') do (
 RmDir "%%A" 2>NUL
)
:: REMOVE FOLDER, IF EMPTY
RmDir %Folder% 2>NUL
endlocal


Example 6
Create SubFolders A-Z and 0-9 and move all files to its corresponding directory. Files that start with special characters in the name are moved to the folder 0-9 like the files that actually start with a number. There I also have some working code.

@ECHO OFF
CLS
IF NOT {%1}=={} (
  CD /d "%~1"
)
ECHO Processing Folder: %CD%

FOR %%f IN (A B C D E F G H I J K L M N O P Q R S T U V W X Y Z REST) DO CALL :MoveFiles "%%f"
GOTO :EOF

:MoveFiles
ECHO Processing: %1 ...
IF %1=="REST" Goto :MoveRest
IF NOT EXIST %1 MD %1
FOR %%f IN (%1*) DO MOVE "%%f" %1>NUL
GOTO :EOF

:MoveRest
IF NOT EXIST 0-9 MD 0-9
MOVE * 0-9>NUL
GOTO :EOF


I wrote some blog posts about some of the advanced batch topics, which you can find at the following URLs, if you are interested.

http://www.roysac.com/blog/2009/05/ms-dos-commands-wild-cards-inputoutput.html
http://www.roysac.com/blog/2009/05/microsoft-internet-explorer-search.html


 




Qlemo"Batchelor", Developer and EE Topic Advisor
Top Expert 2015

Commented:
Cumbrowski,
I'm not getting how you came to the conclusion t0t0 answered your question to 100%. Your test case did fail in some cases. The test case was not part of the original question. The parts of the original question are (also and first) answered by oBdA and me. It's not about getting points, but I do not understand your decision.

Further, the correct treatment of all special characters is a problem in batch files, and AFAIK not feasible, whether for text or file names. The only secure solution is to use something else, and VBS is the next logical step.

BTW, {} and [] (and some more) are no special characters but when using file completition on command line. It's absolutely no problem to use    copy nul   a[1]b  . So no special treatment needed, opposed to what you state in your "advanced" batch topic (which is a good collection of what you can get by issuing cmd /? and set /?).

If you want to see advanced topics, have a look at my article: http://beta.experts-exchange.com/articles/Programming/Languages/Scripting/Shell/Batch/Advanced-DOS-batch-pitfalls.html. It does not cover the "special characters" thread, because that one is to burn one's fingers only, as there is no 100% solution with pure (poor) cmd.exe means.

Commented:
Cumbrowski

I haven't had time to read your last two comments however, please be assured I will do so over the next few days or so.

Qlemo

Neither yours, nor oBdA's code solved the question for filenames containing exclamation marks AND ceret signs - the original filespec with a clear reason as to why the passing of the value is treated as it is at the CALLed end of the code. For example, oBdA's code included the clumsy "SET FName=%FName:^^^^=^^%" attempt at solving the question.

I took particular umbrage at the fact you said my code did not work. My code was clean, uncluttered, uncomplicated and did the job - and was the first program to do so. Creidt was laos given for a deeper discussion of related issues.

Please allow me to enjoy the glory of a few well-desrved points and the grade 'A'. I certainly do not have issue with how Cumbrowski has judged wich code he chose to accept as the solution to this interesting question.
Qlemo"Batchelor", Developer and EE Topic Advisor
Top Expert 2015

Commented:
Ok, now I see why you state our solution did not work - though the reason is wrong. Both solutions DID work with caret and exclamation mark. The part not working was the SPACES in the PATH, which I did not pay attention earlier.

And I stay with my statement that your code is not working if  - forever reason -  DE is active.

Author

Commented:
Olemo,

As I said, the question itself was answered. That it opened up another big can of worms was unexpected, but beyond the scope of the original question. I realized that the problem is much bigger and that Experts-Exchange is probably not the best place to discuss it further.

Regarding the special characters mentioned in my article. It does not say anything about command line usages. The article is about BATCH scripting. (= .BAT files).  Many of the stuff in that article cannot be found in the help to the CMD or any other command. Some stuff might be "hidden" somewhere. I learned that you will not get to everything there is available to use by starting with the the "HELP" command  and then working your way down E.g. HELP <COMMAND> etc. Some stuff was nowhere mentioned or ambiguous and unclear on the MSDN web site and knowledge base on the web.

I came across your other article already and even left a comment with some suggestions there. :) I liked the article itself and what it included, just the presentation of it made it a little difficult to follow, which is more of a style issue and not related to  the content itself.

Did end up doing what you suggested and used VBScript instead, not always because of the limitations of BATCH, but its performance. It is just too slow in some cases. However, it can have advantages over VBS in many cases. It's also easier to share, because there is less risk involved for somebody to run a BATCH script of yours than execute a VBScript "program". The Batch examples  that I provided are good examples to proof my point. I used to do the same with VBScript, until I came across the elegant and fast BATCH solutions to solve the same problems.


You seem to be a bit upset about my decision regarding the closure of the question. I might not communicated very well that I appreciated your expert input and the time that you took looking into the subject. I do appreciate it, which is the reason why I suggested to take the discussion maybe elsewhere.

Do more with

Expert Office
Submit tech questions to Ask the Experts™ at any time to receive solutions, advice, and new ideas from leading industry professionals.

Start 7-Day Free Trial