Removing Special Characters FOR Loop

Any pc / Any model
May 3, 2009 at 09:55:55
Specs: Windows XP and Vista, 4 Gigabytes
I know that I can use the following method to remove special characters away from a folder name:
:: Request the name of the folder from the user
SET /P folder=Folder Name:
Set folder=%folder:\= %
Set folder=%folder:/= %
Set folder=%folder:.= %
Set folder=%folder:@=%
Set folder=%folder:#=%
Set folder=%folder:$=%
Set folder=%folder:%=%
Set folder=%folder:^=%
Set folder=%folder:&=%
Set folder=%folder:*=%
Set folder=%folder:(=%
Set folder=%folder:)=%
Set folder=%folder:+=%
Set folder=%folder:==%
Set folder=%folder:{=%
Set folder=%folder:}=%
Set folder=%folder:[=%
Set folder=%folder:]=%
Set folder=%folder:'=%
Set folder=%folder:"=%
Set folder=%folder:;=%
Set folder=%folder::=%
Set folder=%folder:<=%
Set folder=%folder:>=%
Set folder=%folder:,=%
Set folder=%folder:?=%
Set folder=%folder:|=%
Set folder=%folder:`=%
Set folder=%folder:~=%
Echo %folder%
@pause

Is there an easier method such as a FOR Loop that will perform this same task?


See More: Removing Special Characters FOR Loop

Report •


#1
May 3, 2009 at 18:13:55
for things like this, don't use batch. Even if it can be done, it would be like what you posted. use a tool especially designed for the job of text processing. here's a vbscript that uses regular expression.
Set RegEx = New RegExp
RegEx.Pattern = "[^a-zA-Z0-9]+"
RegEx.IgnoreCase = True
strTest = "start#$&end"
strreplace=RegEx.Replace(strTest, "")
WScript.Echo strreplace

save the script as myscript.vbs and in your batch, use a for loop to get the result which will be the string that has special characters removed.

@echo off
for ..... (cscript /nologo myscript.vbs) do (
 ....
)

NB. you can do everything in vbscript for renaming the folders..but i will leave it to you to explore yourself.

Unix Win32 tools | | Gawk for Windows|


Report •

#2
May 3, 2009 at 18:22:07
Thanks for the response.

I am aware that I can do other things with things like VBScript. However I am trying to accomplish these items within 1 batch file. This batch is utilized by multiple various technicians.

I am trying to make everything as simplified for them as possible. I was trying to do everything in one script so they do not have to be concerned with a bunch of different bat, vbs and other files that do different functions.

If there is a way to accomplish it in a bat file, I would like to keep it there.

The above does work to a point however I was hoping to maybe store ~!@#$%^&*()+`=<>,.?/|\;:'"{}[] in a variable and then a for loop parse to remove each of those out of %folder% variable if they are there.

I am just not sure how to write that.

Wayne
Computer Repair


Report •

#3
May 3, 2009 at 18:27:15
so do everything in vbscript including renaming your folders. put the command "cscript /nologo myscript.vbs" in your batch. you have 1 batch file with only 1 line right ? If not, your technicians can just type that command on the command prompt everytime they want to use it, nothing that complicated right?

Unix Win32 tools | | Gawk for Windows|


Report •

Related Solutions

#4
May 3, 2009 at 18:29:10
Oh no. I have a Batch file with 960 lines in it. This is just one portion of it.

Report •

#5
May 3, 2009 at 18:43:17
@ghostdog
Have you made any changes to your signature lately? Every time you have posted on this thred the next post gets indented and the headed font colo(u)r is not default.

@scrfix
Some of the commands you posted won't even work, most notably %folder:==% and %folder:~=%

Most of the rest could be changed using:

for %%a in ("|" ">" "<" ....) do call set %%folder:%%~a=%%

But you would still need to have lines for "*" and "?" because the for loop interprets them as wildcards and expands them to file names.


Report •

#6
May 3, 2009 at 18:48:38
Judago,

Thanks. I will try that.
I know some of them will not work. I was testing them after I wrote and and I could not edit that message to change it. I also did not want to update by replying for fear that someone would not reply to me thinking that someone else already did.

As an update:
Set folder=%folder:\= %
Set folder=%folder:/= %
Set folder=%folder:.= %
Set folder=%folder:!=%
Set folder=%folder:@=%
Set folder=%folder:#=%
Set folder=%folder:$=%
REM Set folder=%folder:%=% /* This does not work. Not sure how to get a % sign to work. */
REM Set folder=%folder:^=% /* This does not work. Not sure how to get a ^ sign to work. */
REM Set folder=%folder:&=% /* This does not work. Not sure how to get a & sign to work. */
REM Set folder=%folder:(=% /* This does not work. Not sure how to get a ( sign to work. */
REM Set folder=%folder:)=% /* This does not work. Not sure how to get a ) sign to work. */
REM Set folder=%folder:+=% /* This does not work. Not sure how to get a + sign to work. */
Set folder=%folder:{=%
Set folder=%folder:}=%
Set folder=%folder:[=%
Set folder=%folder:]=%
Set folder=%folder:'=%
Set folder=%folder:"=%
Set folder=%folder:;=%
Set folder=%folder::=%
REM Set folder=%folder:<=% /* This does not work. Not sure how to get a < sign to work. */
REM Set folder=%folder:>=% /* This does not work. Not sure how to get a > sign to work. */
Set folder=%folder:,=%
Set folder=%folder:?=%
REM Set folder=%folder:|=% /* This does not work. Not sure how to get a | sign to work. */
Set folder=%folder:`=%
REM Set folder=%folder:~=% /* This does not work. Not sure how to get a ~ sign to work. */

REM Set folder=%folder:==% /* This does not work. Not sure how to get a = sign to work. */
REM Set folder=%folder:*=% /* This does not work. Not sure how to get a * sign to work. */


Report •

#7
May 3, 2009 at 18:55:54
I have removed my sig, but it seems its still there in this thread. If making changes to the sig can cause changes to this forum thread, i guess its not very good after all.

Report •

#8
May 3, 2009 at 18:59:08
This forum allows html. Since it does that there will always be that risk. If something is not closed properly or is using blockquotes or other HTML codes then weird stuff like that will happen. Unknown as to why this is happening. I didn't look at the source code.

Although it does appear to have cleared up since the signature was removed off the last message. The other messages still have the signature on it.

Wayne
Computer Repair


Report •

#9
May 3, 2009 at 19:10:42
For the =,~,% and * I know of no way at all to get it to work with that method, the rest of should work with the for loop I posted.

To strip out the rest could be striped out by a for /f loop.

:aster
for /f "tokens=1,* delims=*" %%a in ("%folder%") do (
if not "%%b"=="" set str=%%a%%b&&goto aster
)

The same works with a "%", "~" and "=", but for the percentage sign you need to specify delims-%%. I would use this after the other for loop to avoid conflicting characters.

@ghostdog
I'm surprised the old sig is still present, I thought that the forum retroactively changed them, maybe it only happens once a week or so, like user message lists.

Well at least it's not indenting any more, you could try editing the post (I know you can't change the sig.) to see if it applies your new sig.


Report •

#10
May 3, 2009 at 19:18:19
I tried the following just like you have above there:

@echo off
:FOLDERNAME
Echo Enter the name of the backup folder on the hard drive and then press Enter.
SET /P folder=Backup Folder Name:
for %%a in ("~" "`" "!" "@" "#" "$" "%" "^" "&" "(" ")" "+" "{" "}" "[" "]" ":" ";" "'" "<" ">" "," "." "/" "\" "|") do call set %%folder:%%~a=%%

Echo You said your backup folder name located on the backup drive will be %folder%.
@pause

I received the following error:
Enter the name of the backup folder on the hard drive and then press Enter.
Backup Folder Name: Wayne%$#4@@
Environment variable Wayne%$#4@@ not defined
Environment variable Wayne%$#4@@ not defined
Environment variable Wayne%$#4 not defined
Environment variable Wayne%$4@@ not defined
Environment variable Wayne%#4@@ not defined
=% was unexpected at this time.
Environment variable Wayne%$#4@@ not defined
Environment variable Wayne%$#4@@ not defined
Environment variable Wayne%$#4@@ not defined
Environment variable Wayne%$#4@@ not defined
Environment variable Wayne%$#4@@ not defined
Environment variable Wayne%$#4@@ not defined
Environment variable Wayne%$#4@@ not defined
Environment variable Wayne%$#4@@ not defined
Environment variable Wayne%$#4@@ not defined
You said your backup folder name located on the backup drive will be Wayne%$#4@@
.
Press any key to continue . . .


I even tried it without the %. Same errors.
Any ideas?


Report •

#11
May 3, 2009 at 19:37:28
The below seems to be working for me, it could easily be brought down to fewer lines:

for %%a in ("`" @ # "^" "&" "(" ")" + { } [ ] ":" ";" "'" "<" ">" "," . / \ "|") do call set folder=%%folder:%%~a=%%
set folder=%folder:"=%
:aster
for /f "tokens=1,* delims=*" %%a in ("%folder%") do (
if not "%%b"=="" set folder=%%a%%b&&goto aster
set folder=%%a
)
:perc
for /f "tokens=1,* delims=%%" %%a in ("%folder%") do (
if not "%%b"=="" set folder=%%a%%b&&goto perc
set folder=%%a
)
:equal
for /f "tokens=1,* delims==" %%a in ("%folder%") do (
if not "%%b"=="" set folder=%%a%%b&&goto equal
set folder=%%a
)
:tide
for /f "tokens=1,* delims=~" %%a in ("%folder%") do (
if not "%%b"=="" set folder=%%a%%b&&goto tide
set folder=%%a
)
set folder=%folder:$=%
set folder=%folder:!=%
echo %folder%
pause

For some reason ! and $ didn't play nice with the for loop.....

[edit]minor fix[/edit]


Report •

#12
May 3, 2009 at 19:52:35
Try the following code: When it asks you for the name, type in <Wayne> you receive ,= for the results instead of Wayne. Any ideas?

Hey Judago, do you mind if I ask you a couple of other items that I am working on with this same script? I have portions of them done but need to get them to work properly.

:FOLDERNAME
Echo Enter the name of the backup folder on the hard drive and then press Enter.
SET /P folder=Backup Folder Name:
for %%a in ("`" "@" "#" "^" "&" "(" ")" "+" "{" "}" "[" "]" ":" ";" "'" "<" ">" "," "." "/" "\" "|") do call set folder=%%folder:%%~a=%%
:aster
for /f "tokens=1,* delims=*" %%a in ("%folder%") do (
if not "%%b"=="" set folder=%%a%%b&&goto aster
)
:perc
for /f "tokens=1,* delims=%%" %%a in ("%folder%") do (
if not "%%b"=="" set folder=%%a%%b&&goto perc
)
:equal
for /f "tokens=1,* delims==" %%a in ("%folder%") do (
if not "%%b"=="" set folder=%%a%%b&&goto equal
)
:tide
for /f "tokens=1,* delims=~" %%a in ("%folder%") do (
if not "%%b"=="" set folder=%%a%%b&&goto tide
)
set folder=%folder:$=%
set folder=%folder:!=%
Echo You said your backup folder name located on the backup drive will be %folder%.
@pause


Report •

#13
May 3, 2009 at 20:01:08
Ok, fixed that little hitch with two double quotes.
for %%a in ("<" ">" "`" @ # "^" "&" "(" ")" + { } [ ] ":" ";" "'" "," . / \ "|") do call set "folder=%%folder:%%~a=%%"
set folder=%folder:"=%
set folder=%folder:$=%
set folder=%folder:!=%
call :sub *
call :sub "="
call :sub ~
call :sub %%%%
goto output

:sub
for /f "tokens=1,* delims=%~1" %%a in ("%folder%") do (
if not "%%b"=="" set folder=%%a%%b&&goto sub
set folder=%%a
)
goto :eof
:output
echo %folder%
pause

[edit]same but smaller[/edit]


Report •

#14
May 3, 2009 at 20:23:52
Okay, I didn't see any difference at a glance in the code however that works. There is a different error that I am not sure if we can do anything about
Type in Wayne<> for the name:
Errors: > was unexpected at this time.

Your newest code repaired the above error. I will test.


The other questions I wanted to get your help on if you don't mind. These are acutally in separate posts:

1. Listing and using all of the non-active profiles in a local computer. These are the profiles that are not the system ones and not the one that the batch file is being run from.

I know that I can get the current user:
for /f "tokens=3 delims=\" %%i in ("%USERPROFILE%") do (set puser=%%i) 2>&1
echo %puser%
@pause

I know that I can list and exclude the ones that I know about with this:
@echo off
for /f "tokens=*" %%a in ('dir c:\docume~1 /b /ad') do call :process "%%a"
goto :eof

:process
if [%1]==["Administrator"] goto :eof
if [%1]==["All Users"] goto :eof
if [%1]==["Default User"] goto :eof
if [%1]==["LocalService"] goto :eof
if [%1]==["NetworkService"] goto :eof
cd\docume~1
pause
:eof

How do I capture and use the rest of what is there? Let's say there are 5 profiles, Tina, Tony, Owner, Wayne, Thomas. We are running the batch file from Owner. I want to be able to capture Tina, Tony, Wayne and Thomas into separate variables let's say user2, user3, user4, user5, etc etc etc. The number of variables necessary would depend on how many user accounts there are.

2. I am running into an insufficient memory error. This is being caused by too many characters in the destination of XCOPY (greater than 254). I cannot use XXCOPY or Robocopy to work around this as everyone is suggesting. I would like the get the length of the path that XCOPY is copying from and based upon that number returned if it is greater than 230, I would like to either auto truncate the files or stop xcopy, automatically rename the destination folder (%folder%) on the destination drive (%drive%) and then continue XCOPY.
I know I can get length utilizing a modification of this code:

:: Send the length of the variable %MyVar%
:: to the variable %length%
set #=%MyVar%
set length=0
:loop
if defined # (set #=%#:~1%&set /A length += 1&goto loop)
echo MyVar is %length% characters long!

Wonder if you have any thoughts.


Report •

#15
May 3, 2009 at 20:46:53
Try the edited version I re-posted above wayne<> works for me with it.

1. %userprofile% does not necessarily contain the current user name if the username has been changed at some stage, try %username% if you want the current username.

To add to that script simply add:

set /a cnt+=1
set var%cnt%=%1

After all of the unwanted folders are filtered of course. You will have sequentially numbered variables var1, var2.... with the folders that are not excluded.

3.
Have you tried short filename aliases? That are used for dos compatibility but almost all command line programs should be able to use them.

To find what the alias is:

for %%a in ("full path") do echo %%~sfa

The only problem is that it may cause some problems with copying long file names, but it may not, it is worth a try anyway.....


Report •

#16
May 3, 2009 at 21:26:19
I tried the edited version. Works great.

Ref: Capturing Non Active Profiles
I thought about using username however decided against it for that same reason that you mentioned. I work on plenty of computers where HP automatically creates an Owner Profile and the technician instead of deleting that profile and creating a whole different username/profile, they just rename the username for the client. Seemless to the client but not to Windows. So if I filter out the username instead of the profile name I could essentially be filtering out Tom instead of Owner. Isn't that correct?

set /a cnt+=1
set var%cnt%=%1

Okay, so set variable cnt as an expression and then add 1 to it.
The set var%cnt%=%1 (I am not sure what that does)

Ref: Short File Names
I do utilize short file names right now. The one problem I have with a short file name is the following command:
If Exist %root%MYMUSIC %backupcmd% %root%MYMUSIC "%drive%%rootcombo%My Music"

It doesn't copy. You can replace %root% with C:/ and %backupcmd% with xcopy and switches
%drive%%rootcombo% is simply destination drive.

It works with every other command I have which is a lot of them except for this one.

When I do:
If Exist "%root%MY MUSIC" %backupcmd% "%root%MY MUSIC" "%drive%%rootcombo%My Music"
It works no problem.

I would like to utilize long file names because of this and the fact that I pinpointed the issue to the folder name on the destination drive I was copying to.

When I was testing I named the folder Waynes Backup Folder. I got an insufficient memory error because I have some substantially long folder names within folders and the AVI names are even longer.

Strangely enough, I figured it would be that it was too long so I manually renamed the video to 1.avi and then reran the script. Same error. I then changed the name back and renamed the destination folder to Backup and it worked just fine. I cannot answer why. I just know the events that brought me to the solution.

Wayne


Report •

#17
May 4, 2009 at 00:40:07
set /a cnt+=1
set var%cnt%=%1

Okay, so set variable cnt as an expression and then add 1 to it.
The set var%cnt%=%1 (I am not sure what that does)

@echo off
set cnt=1
for /f "tokens=*" %%a in ('dir c:\docume~1 /b /ad') do call :process "%%a"
goto :eof

:process
if [%1]==["Administrator"] goto :eof
if [%1]==["All Users"] goto :eof
if [%1]==["Default User"] goto :eof
if [%1]==["LocalService"] goto :eof
if [%1]==["NetworkService"] goto :eof
set /a cnt+=1
set var%vnt%=%1
::%1 is the file name from the for loop
pause
:eof

For the second one things get more difficult, if you want to rename the files, what to?

Now I understand your xcopy problem, full path names can be a maximum of 255 characters and xcopy spews out (a rather cryptic in the circumstances) error message if your copy operation exceeds this. You would probably have to run a for /f loop with dir /b /s inside it over the directory to be backed up, count the characters, subtract the destination directory and truncate where necessary.

I'm sure it will be a lot of fun for you to write that one....


Report •

#18
May 4, 2009 at 07:09:43
Seeing it used within the For Loop, now I understand
set var%cnt%=%1.

Yes,

That is what I thought I was going to have to do.
Since I have around 100 places that get backed up I will have to create a sub and just call that sub for all of those backups.

Thanks for all of your help,

Wayne
Computer Repair


Report •

#19
May 4, 2009 at 19:35:21
Hey Judago,

What do I need to do to capture the name of the directories

Here is what I have:
:DISPLAYNAME
set cnt=1
for /f "tokens=*" %%a in ('dir c:\users /b /ad') do call :process "%%a"
goto :eof

:process
if [%1]==["Administrator"] goto :eof
if [%1]==["All Users"] goto :eof
if [%1]==["Default User"] goto :eof
if [%1]==["LocalService"] goto :eof
if [%1]==["NetworkService"] goto :eof
set /a cnt+=1
set var%cnt%=%1

echo %cnt% REM I wanted to see what cnt puts out. It puts out 2,3,4. I need the actual name such as Tony, Tina, Owner, Etc.

::%1 is the file name from the for loop
pause
:eof

Thanks for any assistance. I modified that for vista.


Report •

#20
May 4, 2009 at 19:41:07
If you need the actual directory name just use %1, I thought you wanted sequentially numbered variables........

Report •

#21
May 4, 2009 at 19:49:12
What I currently have in the program right now is:

set user2=
set user3=
set user4=
set user5=
set user6=
set user7=
set user8=
set user9=
etc
etc
etc

These are the variables I am using. This requires the technicians to enter additional profile names. This is where the sequential variables come in however I also need the directory names after that.

If I wanted to echo them back to me from a variable then I would use echo %1

Doh, I just saw your note telling me that.

I will attempt that. Thanks.

Wayne


Report •

#22
May 4, 2009 at 21:31:02
I just realized that I am making a huge project out of something. I was attempting to repeat what I already had when I don't need to. In fact, I can get rid of what I had and replace it with the code that I already have. %1 gives me exactly what I need. The profile usernames.

Hey, the code is giving me the usernames in quotes. I need to get rid of those quotes. I tried:
set %1=%1:"=%
That failed. I also attempted setting a variable to = %1 and that failed. I know why the quotes are there and why they need to be within the for statement. Is there any way to get the %1 to read without them but still read spaces between the names?

If I take the "" away from "%%a" then it returns only default for default user and All for All Users. If I keep the quotes in then it returns "Default", "SCR". etc etc etc

Wayne
for /f "tokens=*" %%a in ('dir c:\users /b /ad') do call :process "%%a"


Report •

#23
May 5, 2009 at 01:39:21
To remove the surrounding quotes on a parameter simply use %~n where n is the parameter number. Beware spaces aren't the only issue, ampersands can cause problems and are valid characters for file/folder names.

Report •

#24
May 5, 2009 at 06:46:28
Thank you very much for your help. I actually remember reading that the other day. Just couldn't remember it.

You just help me realize that the quotes are ok. I was thinking that they would cause problems when trying to copy because it would be looking for "Tony" and not Tony. It will not. It will only look for Tony and it will cover us if some kid decides to put in %I am HaCkerBoy From Hell!! for his profile username or some girl puts in 'Jenny's Power Puff Girls' for hers.

Thanks for everything.


Report •

#25
May 5, 2009 at 08:36:59
You have brought up a very good point that puts me into a dilemma.

I am using the same directory name %1 to create a new directory where I am copying to. This means that if someone uses the profile name "Bobbys %Hacker% Stuff" which is allowed by Windows I will be creating the new directory with the percent signs and the "" which will screw up the copying process I am sure.

What I can do I guess is set a var to = %1 and then send that var through what we already created above:

Speaking of the above. I have come across a strange bug. When I type in the folder name: 4~!~@#Way!@#$%%^&*()=+=ne{}[]:";'<,.?/433|\ (Not that anyone would do this however I was just trying to test and break the code)
The error: > was unexpected at this time. comes up.

When I remove the > I get the following error:
'*' is not recognized as an internal or external command,
operable program or batch file.
You said your backup folder name located on the backup drive will be 4@#Way@#.

Any ideas?


If I change the code a little I can send the var through it and use it for this purpose unless there is a way to use the other one which I am sure there is.

set var=%1

for %%a in ("<" ">" "`" @ # "^" "&" "(" ")" + { } [ ] ":" ";" "'" "," . / \ "|") do call set "var=%%var:%%~a=%%"
set var=%var:"=%
set var=%var:$=%
set var=%var:!=%
call :varsub *
call :varsub "="
call :varsub ~
call :varsub %%%%
goto varoutput

:svarub
for /f "tokens=1,* delims=%~1" %%a in ("%var%") do (
if not "%%b"=="" set var=%%a%%b&&goto sub
set var=%%a
)
goto :whatever
:varoutput


Report •

#26
May 6, 2009 at 01:11:56
First and foremost "goto wherever" need to be "goto :eof" or "exit" so the subroutine terminates and can be called again. Goto :eof is a built in way to exit a script or subroutine, :eof does not have to be present.

The second problem is with using parameters, which are broken up by various standard delimiters, equals is on of the them you need to pass the parameter inside double quotes, then avoid special characters so


set "var=%~1"

Should do the trick.


"Bobbys %Hacker% Stuff"

Now this is a big problem and I don't know how to deal with it, I don't think the double quotes are legal for a username, they are certainly not in file/folder names. Maybe they are two single quotes?

As for the percentage signs, that could be a real pain if %hacker% is a defined variable, if it is the only thing I can think of would be to setlocal, clear all variables, parse the string, then endlocal(to get all of the variables back).

To be honest I kind of wondered why you were excluding so many valid filename characters, it chould make life real hard when dealing with these user profiles.


Report •


Ask Question