# Simple batch file question



## TechUserCJ (Apr 21, 2009)

Hello,

I would like to write a batch file that reads numbers from a text file, and passes them one by one as an argument to another batch file. I did some reading on the web, and here's what I have so far:

for /f %entnum% in (list.txt) DO (

batchcmd %entnum%

)

It doesn't seem to be working. When I try to run it, it says "in was unexpected at this time". How would I implement this task? One question I have is: is: 

is the entire variable name %entnum%, or is it a variable with a wildcard at the end? 

Also, how do I setup batchcmd so that it assigns entnum to a specific variable in batchcmd's code (e.g. %batchnum%)

I would appreciate any suggestions.

Thanks.


----------



## TheOutcaste (Aug 8, 2007)

TechUserCJ said:


> When I try to run it, it says "in was unexpected at this time".


Welcome to TSG!
Since you haven't defined entnum, %entnum% is null. That makes the For loop look like this:

```
For /F In (list.txt) Do (
```
The error is because there is no Loop Variable.
The loop variable is a single character preceded by either one or two percent symbols. One if typed at the Command Prompt, two if in a batch file.
This is what you need:

```
For /F %%A In (list.txt) Do batchcmd %%A
```
You can pretty much use any character you can type (except ~ and %) for the Loop Variable (A in this case). Best to avoid numerals, as numerals are used with Batch Parameters, and the special characters, *!*,* ^*,* &*,* <*,*>*, and *|*
They can be used, but the last 5 have to be escaped, but doing so is just asking for odd glitches to happen.

In Batchcmd, use this to assign the passed variable (batch parameter):


```
Set batchnum=%1
```
See Call /? for more info on Batch parameters.
See For /? for more info on the For statement.

HTH

Jerry


----------



## TechUserCJ (Apr 21, 2009)

Thanks very much. That reply was very helpful. I managed to get the for loop working if I integrated into batchcmd. However, I'm still having trouble getting batchcmd to accept an argument via another batch file with the for loop in it. When I try to pass it off, it seems to be the expression as literal (e.g. so if the variable is %%A, batchcmd will perform the commands on %%A instead of what is stored in that variable.

So, in batchcmd, batchnum has to be set to %1? Is that the only accepted variable name for the first argument that a batch file is called with to be stored in?

I'm thinking that I might need to do something with delayed variable expansion, but I'm not quite clear on how that works.

Also, do you have any links that you'd recommend for tutorials or information on batch commands? I'm trying to familiarize myself with batch programming in the Windows XP environment. I was reading at http://www.robvanderwoude.com/index.php, and while it seems to be a good resource, it is a little too generic for me (i.e. not focused on XP enough), and doesn't explain the syntax as intuitively and clearly as I'd like. Any suggestions would be appreciated.

Thanks.


----------



## Squashman (Apr 4, 2003)

You need to use CALL.

```
For /F %%A In (list.txt) Do CALL Batch2.bat %%A
```
Why don't you show us the code for the second batch file while you are at it to make sure you are using the passed variable correctly.


----------



## TheOutcaste (Aug 8, 2007)

Thanks for catching that Squashman. Without using Call, it never returns to do the next statement after the For loop.

Either way, it's the current value of the loop variable (%%A) that gets passed.

In the second batch, you can't refer to the parameter as %%A, you have to use %1. Note that if %%A contains spaces, it needs to be in double quotes, or the 2nd batch file will see it as multiple parameters instead of just one. %1 would be everything up to the 1st space, %2 the next section, etc

```
For /F %%A In (list.txt) Do CALL Batch2.bat "%%A"
```
Passed parameters, or values entered on the command line, are referred to by number, 1-9. You can pass more than 9; you then have to use shift to access the additional values.

DOS and VB Scripting Links
Command-line reference A-Z
Using batch parameters
Windows 95/98/ME Batch file Tutorial (Still a good basic reference for WinNT/2K/XP)
Batch File Functions for NT4/2000/XP/2003
Rob van der Woude's Scripting Pages
Microsoft Script Center
Beginners Guides: WindowsXP Command Prompt
Beginners Guides: Understanding and Creating Batch Files

HTH

Jerry


----------



## TechUserCJ (Apr 21, 2009)

Hey all,

Thanks for the replies. I realized that I am still having trouble with the batch file I wrote. Here is the code:

@echo off

Set %%W = 1

for /f %%W in (numlist.txt) DO (


xcopy /y /i C:\dir1\*%%W* C:\dir2\

)

The problem is, it seems to repeatedly search for certain numbers in numlist, but not others. Is the problem that %%W is getting incremented over the course of the for loop? I want %%W to get set to the numbers in the list without being incremented. I suppose I should use another variable to store the number extracted from numlist.txt on a given iteration. How do I refer to the number from numlist for a given iteration?

Thanks.


----------



## TheOutcaste (Aug 8, 2007)

TechUserCJ said:


> @echo off
> Set %%W = 1
> for /f %%W in (numlist.txt) DO (
> xcopy /y /i C:\dir1\*%%W* C:\dir2\
> )


 Set %%W = 1
This line creates a variable named %W (not %%W)*** and sets it to 1.
I'm not sure what you have this in here for if you are reading the numbers from the numlist.txt file. It's not needed.

***A batch file removes percent symbols when it processes lines and expand variables, so if you want a percent symbol, you have to double it.
Example, at the command line type *Echo 100%*
It will display *100%* on screen
Put that in a batch file and it will display *100* -- the percent symbol is removed.
In a batch file you have to use *Echo 100%%* to display *100%*

Also, best to avoid percent symbols for variable names. The percent symbol is a special character, used for Loop variables, Batch parameters, and used when you want to access the contents of a variable rather than it's name.

The code you've shown will read each _*line*_ from numlist.txt, put that in the loop variable, and use it in the next line. The numbers in numlist.txt have to be on separate lines.
So, if numlist looks like this:
1
5
7
125
The loop will execute 4 xcopy lines like this:
xcopy /y /i C:\dir1\**1** C:\dir2\
xcopy /y /i C:\dir1\**5** C:\dir2\
xcopy /y /i C:\dir1\**7** C:\dir2\
xcopy /y /i C:\dir1\**125** C:\dir2\

The *%%W* will be replaced with the current value read from numlist.txt, which I've shown in red.
It looks like you are trying to copy files that have a certain number someplace in the file name.
Using *C:\dir1\*X** with Xcopy or Dir won't work the way you think. Windows doesn't like having multiple * wildcards.

For example, I created a folder with 1000 files named Test*X*File.txt with *X* running from 1 to 1000, then ran the loop.

xcopy /y /i C:\dir1\**1** C:\dir2\
This should have copied only 301 files. It copied 693, including ALL files with a 2 digit number
xcopy /y /i C:\dir1\**16** C:\dir2\
This copied 54 files, it should only have copied 20 (all with 16 and all of the 16X)
and this
xcopy /y /i C:\dir1\**912** C:\dir2\
copied 20 files, not just one:

```
Test106File.txt
Test126File.txt
Test146File.txt
Test166File.txt
Test186File.txt
Test305File.txt
Test325File.txt
Test345File.txt
Test365File.txt
Test385File.txt
Test504File.txt
Test524File.txt
Test544File.txt
Test564File.txt
Test584File.txt
Test703File.txt
Test723File.txt
Test743File.txt
Test763File.txt
Test783File.txt
Test912File.txt
```
If you want to try it out yourself, this following file will


Create C:\Dir1 if needed
Create 1000 files named Test*X*File.txt
Run the loop to do the xcopy command using all numbers from 1 to 1000 for *X*
Once Xcopy has copied the files to Dir2, it will generate a sorted directory listing in *C:\DirResult\Files Found using X.txt* for each number *X*
It then deletes all files in Dir2 so it will get a fresh start for each number


```
@echo off
If Not Exist C:\Dir1 MD C:\Dir1
If Not Exist C:\DirResult MD C:\DirResult
If Exist C:\Dir1\Test1File.txt Goto _start
>C:\Dir1\Test1File.txt Echo A
For /L %%I In (2,1,1000) Do Copy C:\Dir1\Test1File.txt C:\Dir1\Test%%IFile.txt>Nul
:_start
For /L %%W In (1,1,1000) Do (
Echo %%W
xcopy /y /i C:\Dir1\*%%W* C:\Dir2\
 >"C:\DirResult\Files Found using %%W.txt" Dir /B /ON C:\Dir2\Test?File.txt 
>>"C:\DirResult\Files Found using %%W.txt" Dir /B /ON C:\Dir2\Test??File.txt
>>"C:\DirResult\Files Found using %%W.txt" Dir /B /ON C:\Dir2\Test???File.txt 
>>"C:\DirResult\Files Found using %%W.txt" Dir /B /ON C:\Dir2\Test????File.txt
Del /Q c:\Dir2\*.*
)
```
Trying to copy files based on them having a number someplace in the name can get quite involved.
It would help to know the exact format of the file names, and just what you are trying to accomplish.

HTH

Jerry


----------

