# [Windows Batch] String Replace with variable



## scrfix (Jun 29, 2011)

I have tried a few things. I am attempting something and cannot get it to work. I need some help. Hoping someone in here has enough exerience with batch files to help out.

*Goal:* To remove what virtual drives are currently used from the string.
*Notes:* I set up two virtual drives. One that is a UNC and another on my own drive for testing. I have the FOR statement working to give me just the letter F or the letter R. I am attempting to capture the letter being utilized for each virtual drive and subtract it from a variable string named _alphabet.
Ending result should be an echo statment of ABCDEGHIJKLMNOPQSTUVWXYZ (Missing the letters F and R since those are being utilized as a virtual drive.)
C:\>SUBST
F:\: => UNC\foldertest\test1
R:\: => C:\test2

I know the following works if it is not in a FOR loop.

```
@echo on
set _ab=ABCDEFGHIJKLMNOPQRSTUVWXYZ
set _ab=%_ab:F=%
echo %_ab%
pause
```
However I need it to work in a FOR loop.
Some different things I have attempted:

```
::variables
set _alphabet=ABCDEFGHIJKLMNOPQRSTUVWXYZ
Setlocal EnableDelayedExpansion
FOR /F "tokens=1 delims=:" %%I in ('SUBST') DO (
set _dl=%%I
CALL SET _alphabet=!_alphabet:%_dl%=!
)
EndLocal
ECHO %_alphabet%
pause
```


```
::variables
set _alphabet=ABCDEFGHIJKLMNOPQRSTUVWXYZ
FOR /F "tokens=1 delims=:" %%I in ('SUBST') DO (
set _dl=%%I
SET _alphabet=%%_alphabet:%_dl%=%%
)
ECHO %_alphabet%
pause
```


```
::variables
set _alphabet=ABCDEFGHIJKLMNOPQRSTUVWXYZ
Setlocal EnableDelayedExpansion
FOR /F "tokens=1 delims=:" %%I in ('SUBST') DO (
set _dl=%%I
SET _alphabet=!_alphabet:%_dl%=!
)
EndLocal
ECHO %_alphabet%
pause
```


```
::variables
set _alphabet=ABCDEFGHIJKLMNOPQRSTUVWXYZ
FOR /F "tokens=1 delims=:" %%I in ('SUBST') DO (
set _dl=%%I
CALL SET _alphabet=%%_alphabet:%_dl%=%%
)
ECHO %_alphabet%
pause
```
If someone can help that would be absolutely outstanding.


----------



## scrfix (Jun 29, 2011)

I know that I can do the following as well and it works. However it is a bit long winded and I know there is a better way to accomplish this:


```
@echo on
::Varibles
set _ab=ABCDEFGHIJKLMNOPQRSTUVWXYZ
:_VIRTUALDRIVECHECK
for /F "tokens=1 delims=:" %%I IN ('SUBST') DO CALL :_VIRTUALDRIVEPROCESS %%I
pause
GOTO _COMPLETED
:_VIRTUALDRIVEPROCESS
if /i [%1]==[A] (
set _ab=%_ab:A=%
GOTO :EOF
)
if /i [%1]==[B] (
set _ab=%_ab:B=%
GOTO :EOF
)
if /i [%1]==[C] (
set _ab=%_ab:C=%
GOTO :EOF
)
if /i [%1]==[D] (
set _ab=%_ab:D=%
GOTO :EOF
)
if /i [%1]==[E] (
set _ab=%_ab:E=%
GOTO :EOF
)
if /i [%1]==[F] (
set _ab=%_ab:F=%
GOTO :EOF
)
if /i [%1]==[G] (
set _ab=%_ab:G=%
GOTO :EOF
)
if /i [%1]==[H] (
set _ab=%_ab:H=%
GOTO :EOF
)
if /i [%1]==[I] (
set _ab=%_ab:I=%
GOTO :EOF
)
if /i [%1]==[J] (
set _ab=%_ab:J=%
GOTO :EOF
)
if /i [%1]==[K] (
set _ab=%_ab:K=%
GOTO :EOF
)
if /i [%1]==[L] (
set _ab=%_ab:L=%
GOTO :EOF
)
if /i [%1]==[M] (
set _ab=%_ab:M=%
GOTO :EOF
)
if /i [%1]==[N] (
set _ab=%_ab:N=%
GOTO :EOF
)
if /i [%1]==[O] (
set _ab=%_ab:O=%
GOTO :EOF
)
if /i [%1]==[P] (
set _ab=%_ab:P=%
GOTO :EOF
)
if /i [%1]==[Q] (
set _ab=%_ab:Q=%
GOTO :EOF
)
if /i [%1]==[R] (
set _ab=%_ab:R=%
GOTO :EOF
)
if /i [%1]==[S] (
set _ab=%_ab:S=%
GOTO :EOF
)
if /i [%1]==[T] (
set _ab=%_ab:T=%
GOTO :EOF
)
if /i [%1]==[U] (
set _ab=%_ab:U=%
GOTO :EOF
)
if /i [%1]==[V] (
set _ab=%_ab:V=%
GOTO :EOF
)
if /i [%1]==[W] (
set _ab=%_ab:W=%
GOTO :EOF
)
if /i [%1]==[X] (
set _ab=%_ab:X=%
GOTO :EOF
)
if /i [%1]==[Y] (
set _ab=%_ab:Y=%
GOTO :EOF
)
if /i [%1]==[Z] (
set _ab=%_ab:Z=%
GOTO :EOF
)
GOTO :EOF
:_COMPLETED
echo %_ab%
pause
```


----------



## scrfix (Jun 29, 2011)

The latest that I attempted before I am heading off to bed was:


```
@echo on
::Varibles
set _ab=ABCDEFGHIJKLMNOPQRSTUVWXYZ
:_VIRTUALDRIVECHECK
setlocal EnableDelayedExpansion
for /F "tokens=1 delims=:" %%I IN ('SUBST') DO CALL :_VIRTUALDRIVEPROCESS %%I
pause
GOTO _COMPLETED

:_VIRTUALDRIVEPROCESS
FOR /F "tokens=*" %%I IN (%_ab%) DO IF /i [%1]==%%I (set _ab=!_ab:%%I=!)&GOTO :EOF
GOTO :EOF
 
:_COMPLETED
echo %_ab%
pause
```
I receive an error:
C:\test>"subst-call-test.bat"
C:\test>set _ab=ABCDEFGHIJKLMNOPQRSTUVWXYZ
C:\test>setlocal EnableDelayedExpansion
C:\test>for /F "tokens=1 delims=:" %I IN ('SUBST') DO CALL :_VIR
TUALDRIVEPROCESS %I
C:\test>CALL :_VIRTUALDRIVEPROCESS F
C:\test>FOR /F "tokens=*" %I IN (ABCDEFGHIJKLMNOPQRSTUVWXYZ) DO
IF /I [F] == [F] (set _ab=%_ab:F=% ) & GOTO :EOF
*The system cannot find the file ABCDEFGHIJKLMNOPQRSTUVWXYZ.*
C:\test>GOTO :EOF
C:\test>CALL :_VIRTUALDRIVEPROCESS R
C:\test>FOR /F "tokens=*" %I IN (ABCDEFGHIJKLMNOPQRSTUVWXYZ) DO
IF /I [R] == [R] (set _ab=%_ab:R=% ) & GOTO :EOF
*The system cannot find the file ABCDEFGHIJKLMNOPQRSTUVWXYZ.*
C:\test>GOTO :EOF
C:\test>pause
Press any key to continue . . .
C:\test>GOTO _COMPLETED
C:\test>echo ABCDEFGHIJKLMNOPQRSTUVWXYZ
ABCDEFGHIJKLMNOPQRSTUVWXYZ
C:\test>pause
Press any key to continue . . .
C:\test>


----------



## scrfix (Jun 29, 2011)

I figured this out.


```
@echo off
::Variables
set _ab=ABCDEFGHIJKLMNOPQRSTUVWXYZ

:_VIRTUALDRIVECHECK
setlocal EnableDelayedExpansion
for /F "tokens=1 delims=:" %%I IN ('SUBST') DO CALL :_VIRTUALDRIVEPROCESS %%I
GOTO _COMPLETED
 
:_VIRTUALDRIVEPROCESS
FOR /F "tokens=*" %%I IN ("%_ab%") DO (set _ab=!_ab:%1=!)&GOTO :EOF
GOTO :EOF
 
:_COMPLETED
echo %_ab%
pause
```


----------



## Squashman (Apr 14, 2005)

So you found your way over here as well. I don't often get over to this forum to help with batch files but yes you made a simple error there and fixed it.

Just wondering what you need this for. Seems like an odd batch file output. Not sure why you are callining another subroutine to get your desired result. Really no need for that. You could do it all in a single For Loop.


----------



## scrfix (Jun 29, 2011)

LOL.. Found my way here. I tried here first and nobody responded back to me. I wanted to see if people were just as helpful or as knowledgeable here as they are on tech guy forums. I found out they were not. I also tried one other spot after this before hitting tech guy forums. No response from there either.

I got it working with your help. I am setting up a script to autoset a drive letter on a backup script. In order to do that I need to know what drive letters are utilized.

The biggest issue I had was I have multiple computers that I am working on with varying degrees of windows updates, some of which I am not virtually or physically connected to that I have to be able to back up their data to an external hard drive.

I tried to make it work within a single loop and could not get it to work. I would rather it in one loop. I ended up having to utilize the call in order to work two for statements together.

I ended up still needing the "delims=: " in the script.

This is so much easier with WMIC LOGICALDISK. It outputs every drive letter used on the computer in the caption column. However since XP was not shipped with this I have to create a script just for XP in case it doesn't have the update that installs this.

In order to do this, I needed to be able to detect virtual drives: done, networked drives: done, physical and dvd drives: done, usb drives: <I have the script but it is not tested. someone else wrote it>.

Whenever I write a script for my technicians or clients to utilize I have to test it on every OS from XP on up (All versions of XP, Vista, 2003, 7, 2008 both 64 bit and 32 bit.) because I never know what operating system they are going to have so it needs to work on all of them.

One of the other issues I am running into is that I am utilizing the SETLOCAL EnableDelayedExpansion in order to get this to work. As soon as I utilize ENDLOCAL that goes away so I am probably going to have to write something to the registry or to a text file to store the available drive letters before I do an ENDLOCAL. This way I can still set the drive letter later on.


Hopefully that answers your questions.


----------



## Squashman (Apr 14, 2005)

Not sure what you mean by autoset a drive letter?

What are you backing up to? A physically attached USB hard drive or to a network drive?

Output your final variable to a temporary text file. You can then read that back in with a set statement.


----------



## scrfix (Jun 29, 2011)

The backup script covers all bases. It can be a network mapped drive, physical hard drive, virtual drive, usb media (As long as there is enough room). It doesn't matter.

I have it all worked out now. I had forgotten about 1 item, floppy drives but I found those in a registry entry.

What I am doing is setting a backup drive letter for my technicians so they don't have to waste the step of going in and setting one.

I was simply just setting the drive letter manually to Z. Well, HP, in its wisdom uses Z for their printer. If Z is taken then my backup script screwed up. Since most of my techs do not know how to batch and I had it hardcoded in there, this created a problem.

So now, I have figured out how to determine every drive letter the operating system has allocated out, subtracted that from my list and then I randomize a letter from what is left. So the backup drive will be letter ? but it will be a letter that is not allocated at that time.

The next step in the pattern is to determine the type of media that is to be backed up to: ie. physically connected hard drive, network mapped drive. I believe I have a plan for this one as far as the connected drives.

I am going to look at all of the connected drives excluding the systemdrive, see if any of them are unformatted first. If there are drives that are unformatted then I will look at these first, if there are not then I will capture the amount of free space for each drive, take whatever drive has the greatest amount of free space and then utilize that one as the backup hard drive. That is the best that I can come up with right now to try to automate the process of setting the backup drive letter to match the one chosen by the script.

The more I can do to automate the technicians jobs the better. This is less training on minor things that they should already know and more training on things they need to know.


----------



## Squashman (Apr 14, 2005)

Personally I think you are wasting alot of time on such a trivial task that should only take them a few seconds.

If you were backing up to a network drive you would never have to know the drive letter because BATCH can use UNC paths.


----------

