Solved

Batch file help with FOR /F

Posted on 2011-03-01
12
1,318 Views
Last Modified: 2012-05-11
Intent:
I want to pull the entries from a text file called 'test.txt' and run commands on them one by one via a batch file.

The text file is very simple.
Contents are computer names:

cha-smbdrm1-l
cha-blloyd-d
cha-mailroom-d
...

The reason I'm doing this is I have a list of computer names in our domain in a txt file,  and I want to push a file to these systems that will disable a particular prompt for updates.
There are a thousand ways to do this, but I chose the Batch file because I'm a bit old school.

The logic runs like this:
Pull a computer name from the TXT file.
Map a drive to that machine.
Copy a file from my machine (or a network location haven't decided yet) to a particular folder on the target.
Remove the mapped drive.
Pull the next computer name from the TXT file...
And so on and so forth.

Here's my batch file:

 
setlocal 
FOR /F %%a in (c:\test.txt) do call :SUB %%a

:SUB

if exist z: (net use z: /delete)
net use z: \\%%a\c$ /user:domain\username Password
copy c:\mms.cfg z:\WINDOWS\system32\Macromed\Flash
if exist z: (net use z: /delete)
  if errorlevel 1 (goto :EOF)
  else (ping -n 2 127.0.0.1 > nul 
  goto :SUB)

:EOF

Open in new window


I'm sure I have the exit strategy wrong with where I have the :EOF being called, but I'm more concerned with the fact that the FOR /F doesn't seem to work.

My results from running this script are mixed.

 Screen cap of running that batch file
1. You can see that the FOR /F command seems to be picking up the correct %%a variables, as it shows it marching through the test.txt file, and taking cha-smbdrm1-l and then cha-smbdrm2-l.

2. However in 2 you can see the variable in the sub routine, which I have specified as %%a is not being correctly filled in.


WHAT I'VE ALREADY TRIED.

1. In the sub routine I've already tried putting in %1 as the variable.  This makes the script work, but it keeps repeating only the first entry in the test.txt file.  The %%a keeps changing, but the variable entered keeps being the first entry.

2. setlocal EnableDelayedExpansion - tried that and put in a set var1=%%a under the FOR command, and referenced it in the sub routine with !var1!.  Same result as if I put in %1 as the variable.
0
Comment
Question by:DKingArxx
12 Comments
 
LVL 53

Accepted Solution

by:
Bill Prew earned 125 total points
ID: 35011518
When you call a subroutine (or another bat file) via the CALL command, the arguments you pass are accessed via %1, %2, %3, ... etc.  So in your case you want to change:

net use z: \\%%a\c$ /user:domain\username Password

to

net use z: \\%1\c$ /user:domain\username Password

FOR loop variables like %%a are only available inside the FOR loop, and technically the called routine is no longer in that context, so you can't reference the %%a.

The logic in the :SUB itself looks like it could use a little work too, but I'll start by answering your initial question.

~bp

~bp
0
 
LVL 33

Expert Comment

by:knightEknight
ID: 35011531
Rather than mounting a drive each time, consider using a UNC instead:

   copy  c:\mms.cfg  \\%%a\c$\WINDOWS\system32\Macromed\Flash

Run the entire batch file as the same user you were using to map the Z: drives.
0
 
LVL 37

Expert Comment

by:Neil Russell
ID: 35011580
You know you could do this with a group policy preference in a few minutes.
Old school is an excuse i used to use until i needed to look for a new job and discovered I was OLD SCHOOL!!!

We used to walk infront of cars waving a red flag ;) But times move on ;)
0
Best Practices: Disaster Recovery Testing

Besides backup, any IT division should have a disaster recovery plan. You will find a few tips below relating to the development of such a plan and to what issues one should pay special attention in the course of backup planning.

 

Author Comment

by:DKingArxx
ID: 35011592
@BillPrew

You know? I could SWEAR I tried putting %1 in as the variable.  I think I even mention it in my original post.

But this time I tried it and it worked!

Thank you, Bill!

And yes, I know the rest of my :SUB needs some work. :D
Just wanted to put a little pause in there between mapping attempts.

@knightEknight

Not a bad idea, to run the script with the permissions already in place.  Not what I was asking, but thanks for looking.
0
 

Author Comment

by:DKingArxx
ID: 35011618
@NeilSr

My Boss has the Group Policy editing locked down pretty tight.  I could get in using the Domain Admin password I have but don't feel like explaining myself 30 times and writing an impact report and then having it discussed in committee for 2 weeks before getting grudging permission to go ahead.

Especially when I can just DO IT!

<hits enter>

Like dat!
0
 

Author Closing Comment

by:DKingArxx
ID: 35011693
VERY quick reply and the answer was just what I was looking for.
0
 
LVL 53

Expert Comment

by:Bill Prew
ID: 35011821
Great, glad that helped. Thanks.

~bp
0
 

Author Comment

by:DKingArxx
ID: 35011855
OKAY.

Problem still.  Maybe closed this too quickly.

Just tried it again with my full file and the behaviour I described before is happening.

It keeps looping with the 1st entry in my TXT file.

Screenshot attached:

 Script repeating first entry of text file
Code is:

 
setlocal 
FOR /F %%a in (c:\test.txt) do call :SUB %%a

:SUB

if exist z: (net use z: /delete)
net use z: \\%1\c$ /user:domain\user Password
copy c:\mms.cfg z:\WINDOWS\system32\Macromed\Flash
if exist z: (net use z: /delete)
goto :SUB

:EOF

Open in new window


Slight edits to remove some of the :SUB entries...of course that just makes my script loop endlessly because it never goes to :EOF.
Aware of that, just wondering why it isn't moving on to the next entry in the TXT file.
0
 
LVL 53

Expert Comment

by:Bill Prew
ID: 35012023
You are stuck in the goto :SUB loop, so never leaving the subroutine.

That should likely either be

goto :EOF

or

exit /b

either of which will exit the subroutine.

~bp
0
 

Author Comment

by:DKingArxx
ID: 35017084
Ah, so when I cleaned that ping crap out of my original code I also removed the goto :EOF.
Let me try that.
0
 

Author Comment

by:DKingArxx
ID: 35018163
Yep. That was it.

Code changed to this and it worked:

 
setlocal 
FOR /F %%a in (c:\computers.txt) do call :SUB %%a

:SUB

if exist z: (net use z: /delete)
net use z: \\%1\c$ /user:domain\username Password
copy c:\mms.cfg z:\WINDOWS\system32\Macromed\Flash
if exist z: (net use z: /delete)
  if errorlevel=1 (goto :EOF)
  ) else (
    ping -n 2 127.0.0.1 > nul
    exit /b
  )

:EOF

Open in new window


Silly loops.

Thank you again, Bill!
0
 
LVL 53

Expert Comment

by:Bill Prew
ID: 35018534
Very welcome.

~bp
0

Featured Post

Master Your Team's Linux and Cloud Stack!

The average business loses $13.5M per year to ineffective training (per 1,000 employees). Keep ahead of the competition and combine in-person quality with online cost and flexibility by training with Linux Academy.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

VALIDATING DATES One method of validating dates is to jam the date into the DATE command and see if it accepts it by examining the system's errorlevel value. A non-zero result indicates failure. A typical example might look something like the fol…
Being a system administrator some time we require to do things remotely, one of them is installing software. Here I am going to tell you how to install software through wmic (Windows management instrument console). I am not at all saying that this i…
In a recent question (https://www.experts-exchange.com/questions/28997919/Pagination-in-Adobe-Acrobat.html) here at Experts Exchange, a member asked how to add page numbers to a PDF file using Adobe Acrobat XI Pro. This short video Micro Tutorial sh…

803 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question