# Batch Script pulling from txt and using txt lines as variables



## Foremore (Feb 4, 2011)

I have been writting backup scripts for a while now and I wanted to make everything very easy to work with and use.
what I want is a batch script that reads off a text file that lists the file locations and sets them to a variable. then using each variable i want to throw it through a for loop sending each location through robocopy command and backing them up to the source directory of the exe.

here are my problems:
below I have posted my code. I have found ways to grab the locations off the text file and make them a variable. What I haven't found is how to send those variables 1 by one through the robocopy command till no more variables exist then leave the for loop. Below is the code I thought that would work but it just exits out of the script without an error. I have edited out some stuff and kept it as simple as I can.


```
@Echo Off
echo ### Mirroring...
 
:: this will grab each line of the locations text file and set it to a variable %%I
:: it will take the variable %%I and use it to know the next location to copy to external using the robocopy command
 
SetLocal EnableDelayedExpansion
 
Set InputFile="C:\locations.txt"
 
For /F "tokens=*" %%I IN (%InputFile%) DO (
Set location="%%I"
 
:: echo location for logging
echo %location% >>%logging%
 
::robocopy command pulling variables from almost everywhere
ROBOCOPY %location% %dest% %what% %options% 
 
::report errorlevel
echo %ERRORLEVEL% >>%logging%
 
 
)
EndLocal
```

I also posted this in the wrong place under software and development... if anyone can let me know how to delete the other or let me know what to do that would be great.


----------



## Foremore (Feb 4, 2011)

update:

So I found a similar forum about this very topic doing something about the same. I looked into how he did it and made my own variation. it will make the variables right but still having difficutly calling them one by one and sending them through the robocopy command. Marked n orange next to the code is my problem.

here is the revision that I thought would work a lot better:


```
echo ### Mirroring...
 
:: set the count for the loop through the robocommand
SET cnt=1
 
:: this will grab each line of the locations text file and set it to a variable %%I
:: it will take the variable %%I and use it to know the next location to copy to external using the robocopy command
SetLocal EnableDelayedExpansion
Set n=
Set _InputFile=locations.txt
For /F "tokens=*" %%I IN (%_InputFile%) DO (
Set /a n+=1
Set _var!n!=%%I
)
:: Line will display the variables just assigned - delete when not needed
Set _
Pause
 
echo ###Please do not close this window! Backup is in progress...
 
 
set DEST=C:\testfinal
set what= /COPYALL /MIR
set options=/R:3 /W:120 /LOG:%roboLog% /NDL /NP /TEE 
 
 
 
:: LOOP through directory listing variables _var(x) until there are no more 
:Start
IF %_var!cnt!%=="" GOTO END    [B][U][COLOR=darkorange]:: this is my trouble:confused:[/COLOR][/U][/B]
SET location=%_var!cnt!%          [B][U][COLOR=#ff8c00]:: this is my trouble idk how to set a temp variable to the current _var# variable[/COLOR][/U][/B]
echo %location% >>%logging%    
 
::robocopy command pulling variables from almost everywhere
ROBOCOPY %location% %dest% %what% %options% 
 
 
::report errorlevel
echo %ERRORLEVEL% >>%logging%
 
 
SET /a cnt+=1 
ECHO %cnt% - the line # we are at & GOTO Start
 
EndLocal
 
:END
```


----------



## TheOutcaste (Aug 8, 2007)

For delayed expansion, you have to use the *!* symbol instead of *%* if the variable is used on the same line it's defined. Everything in a For loop until the closing parenthesis is considered one line.
Though for this you don't need to use a variable, just use the loop variable.
Only reason for delayed expansion is to echo the errorlevel.

```
@Echo Off
echo ### Mirroring...
 
:: this will grab each line of the locations text file and set it to a variable %%I
:: it will take the variable %%I and use it to know the next location to copy to external using the robocopy command
 
SetLocal EnableDelayedExpansion
 
Set InputFile=C:\locations.txt
 
For /F "tokens=* Delims=" %%I IN ('Type "%InputFile%"') DO (

:: echo location for logging
echo %%I>>"%logging%"
 
::robocopy command pulling variables from almost everywhere
ROBOCOPY "%%~I" "%dest%" %what% %options% 
 
::report errorlevel
echo !ERRORLEVEL!>>"%logging%"
 
 
)
EndLocal
```
I've had better luck by not including the quotes in variables. Rather quote the variable when used. In a For loop use the ~ modifier to remove any existing quotes first.

For the second version:
*IF %_var!cnt!%=="" GOTO END*

You _must_ have quotes around the variable on the left. If *%_var!cnt!%* is not defined (the one after the last won't be defined), you end up with this:
*If =="" GOTO END*
Which will give an error.
So you have to use this, which means the file names in the InputFile cannot be quoted:
*IF "%_var!cnt!%"=="" GOTO END*

If the file names are quoted, you end up with this for example:
*If ""C:\My Files""=="" GOTO END.* 
The error will state *C:\My* is not expected, as it's expecting *==* after the 2nd quote.


----------



## Foremore (Feb 4, 2011)

Thanks for the input that helped a ton.


----------



## Foremore (Feb 4, 2011)

So I have now got a working code!  But I want to expand on this just one more time and it should work like I want it to. this code right now just dumps everything into one destination. this makes stuff like favs and documents not in folders all mingled together. I want to dump each loop into a named backup folder. the name is like this: take the string that %%I is storing and get ride of all chars except chars after last "\" and name the folder that. so example: C:\documents and settings\%USERNAME%\desktop this folder would be named desktop and dump everything into that folder till the next loop starts. There are no set amount of chars between the begging and the last "\" so i can't just count over and take whats after. 
I have searched long and hard how to parse out things from strings or another term would be string minipulation... but nothing has helped me understand how to get to the last "\" and make a variable with the remaing chars after it.

here is my code:

```
SetLocal EnableDelayedExpansion
 
Set InputFile=locations.txt
 
For /F "tokens=* Delims=" %%I IN ('Type "%InputFile%"') DO (
:: echo location for logging
 
echo %%I>>"%logging%"
 
[COLOR=darkorange]:: This is where I would think to make a for loop and take what is stored in %%I set it equal to a temp variable called %temp%, [/COLOR]
[COLOR=darkorange]then parse out the remaing chars after the last delims "/" (which is unknown how many there are till the last "\") [/COLOR]
[COLOR=darkorange]and set it to a variable %folder%. but its just so mind blowing for me to think of how that works.:o [/COLOR]
[COLOR=darkorange]after that I would just make my %dest% variable something like j:\backup\ in code before these [/COLOR]
[COLOR=darkorange]for loops and then add %folder% as shown below to complete the destination string for the robocopy command.[/COLOR]
 
::robocopy command pulling variables from almost everywhere
ROBOCOPY "%%~I" "%dest%[COLOR=darkorange]%folder%[/COLOR]" %what% %options% 
 
[COLOR=darkorange]:: If I where to echo %dest%folder% right now it would read [/COLOR]
[COLOR=darkorange][/COLOR] 
[COLOR=darkorange] J:\backup\desktop taking from the example above.[/COLOR]
 
::report errorlevel
echo !ERRORLEVEL!>>"%logging%"
 
EndLocal
 
cls
```
Thanks for all the help. If there is any rating system in these forums let me know and I can give you any praise it will allow me to do.


----------



## TheOutcaste (Aug 8, 2007)

As long as the folders in the *locations.txt* file do not have a trailing slash use *%%~nxI*. This gives just the *N*ame and e*X*tension (if any) of the path.
The name is the text after the last \ upto the last period (if any). The extension is the text after the last period, if any. This works for any string of text you get into the loop variable, it doesn't have to be a real path.

```
ROBOCOPY "%%~I" "%dest%\%%~nxI" %what% %options%
```
So this will work:

```
C:\Documents and Settings\TheOutcaste\My Documents
C:\Documents and Settings\TheOutcaste\My Documents\My Pictures
C:\Stuff\WorkinProgress
C:\Stuff\WorkCompleted
```
This won't:

```
C:\Documents and Settings\TheOutcaste\My Documents\
C:\Documents and Settings\TheOutcaste\My Documents\My Pictures\
C:\Stuff\WorkinProgress\
C:\Stuff\WorkCompleted\
```
Type *For /?* or *Call /?* in a Command Prompt to see what modifiers are available.


----------

