Problem with DOS batch file - FOR loop

  • Thread starter Thread starter Scott Bass
  • Start date Start date
S

Scott Bass

Guest
Hi,



I'm not sure this is the correct newsgroup - if not, can you please suggest

the appropriate one for a DOS batch question? Thanks...



I'd love to code my problem in VBS, PowerShell, Perl, Python, Ruby, ...

anything but DOS. Since I can't, here's my problem: (Note: I can't

install ANY additional s/w on the end user's machines and can't use VBS)



I've got a config file for an application that looks like:



-log "C:\Some\Path To\My Config\File\config.cfg"



I have to parse this file, extracting the value for the logs location into a

variable, in order to search the generated logs after the application

executes. The problem comes from the spaces in the file path.



I've got this code (with lots of debugging stub statements):



setlocal



FOR /F "usebackq tokens=2-5* delims= " %%a IN (`findstr /i /c:-log

"%config%"`) DO (

echo A %%a

echo B %%b

echo C %%c

echo D %%d

echo E %%e



if defined A echo A IS DEFINED

if defined B echo B IS DEFINED

if defined C echo C IS DEFINED

if defined D echo D IS DEFINED

if defined E echo E IS DEFINED



if not dummy==dummy%%a echo A IS NOT BLANK

if not dummy==dummy%%b echo B IS NOT BLANK

if not dummy==dummy%%c echo C IS NOT BLANK

if not dummy==dummy%%d echo D IS NOT BLANK

if not dummy==dummy%%e echo E IS NOT BLANK



if not dummy==dummy%%a set logs=%%a

if not dummy==dummy%%b set logs=%%logs %%b

if not dummy==dummy%%c set logs=%%logs %%c

if not dummy==dummy%%d set logs=%%logs %%d

if not dummy==dummy%%e set logs=%%logs %%e



echo %%logs

)



echo %%logs



It's not ideal, since I could (in theory) have a path with more than 5 space

separated tokens. But not likely, so I can live with this. I have a

feeling the problem could be due to immediate vs. delayed variable

resolution. And I may be using %%var vs. %var% incorrectly.



Ideally, I'd like to retrieve the line from the log, and do a search and

replace on "-log" (s/-log//g in say Perl or vi on Unix). But I can't see

how to do this in a DOS batch file. If there is a way to do a search and

replace in DOS OOTB, that would be great.



Any ideas how to parse the above to return the results equivalent to:



set logs="C:\Some\Path To\My Config\File\config.cfg"



Thanks,

Scott
 
"Scott Bass" wrote in

message news:eiTDo19xKHA.2012@TK2MSFTNGP04.phx.gbl...

> Hi,

>

> I'm not sure this is the correct newsgroup - if not, can you please

> suggest

> the appropriate one for a DOS batch question? Thanks...

>

> I'd love to code my problem in VBS, PowerShell, Perl, Python, Ruby, ...

> anything but DOS. Since I can't, here's my problem: (Note: I can't

> install ANY additional s/w on the end user's machines and can't use VBS)

>

> I've got a config file for an application that looks like:

>

> -log "C:\Some\Path To\My Config\File\config.cfg"

>

> I have to parse this file, extracting the value for the logs location into

> a

> variable, in order to search the generated logs after the application

> executes. The problem comes from the spaces in the file path.

>

> I've got this code (with lots of debugging stub statements):

>

> setlocal

>

> FOR /F "usebackq tokens=2-5* delims= " %%a IN (`findstr /i /c:-log

> "%config%"`) DO (

> echo A %%a

> echo B %%b

> echo C %%c

> echo D %%d

> echo E %%e

>

> if defined A echo A IS DEFINED

> if defined B echo B IS DEFINED

> if defined C echo C IS DEFINED

> if defined D echo D IS DEFINED

> if defined E echo E IS DEFINED

>

> if not dummy==dummy%%a echo A IS NOT BLANK

> if not dummy==dummy%%b echo B IS NOT BLANK

> if not dummy==dummy%%c echo C IS NOT BLANK

> if not dummy==dummy%%d echo D IS NOT BLANK

> if not dummy==dummy%%e echo E IS NOT BLANK

>

> if not dummy==dummy%%a set logs=%%a

> if not dummy==dummy%%b set logs=%%logs %%b

> if not dummy==dummy%%c set logs=%%logs %%c

> if not dummy==dummy%%d set logs=%%logs %%d

> if not dummy==dummy%%e set logs=%%logs %%e

>

> echo %%logs

> )

>

> echo %%logs

>

> It's not ideal, since I could (in theory) have a path with more than 5

> space

> separated tokens. But not likely, so I can live with this. I have a

> feeling the problem could be due to immediate vs. delayed variable

> resolution. And I may be using %%var vs. %var% incorrectly.

>

> Ideally, I'd like to retrieve the line from the log, and do a search and

> replace on "-log" (s/-log//g in say Perl or vi on Unix). But I can't see

> how to do this in a DOS batch file. If there is a way to do a search and

> replace in DOS OOTB, that would be great.

>

> Any ideas how to parse the above to return the results equivalent to:

>

> set logs="C:\Some\Path To\My Config\File\config.cfg"

>

> Thanks,

> Scott




It might be appropriate to start by cleaning out some misunderstandings.

There is no such thing as a "DOS batch file". DOS is an operating system

that was introduced more than 30 years ago. It is only rarely used these

days and it does not exist under Windows XP. Under Windows XP you have the

Console (or Command Prompt), much like the console under non-Microsoft OSs.

Although it's black and character based, it has very little in common with

DOS.



About your batch file - how about something like the code below. Note that

most of its instructions would fail under DOS. And by the way - if you don't

like coding batch files, what prevents you from writing a small VB Script

file? Cscript.exe is native to all current flavours of Windows and the code

would be quite trivial.



@echo off

set Line=x

for /F "delims=" %%a in ('type "d:\temp\test.txt" ^| find /i "-log "') do

set Line=%%a

if x==%Line% goto :eof

set Line=%Line:-log=%

for /F "delims=" %%a in ('echo %Line%') do set LogPath=%%a

echo LogPath=%LogPath%
 
On Sat, 20 Mar 2010, "Pegasus [MVP]" wrote:



>It might be appropriate to start by cleaning out some misunderstandings.

>There is no such thing as a "DOS batch file". DOS is an operating system

>that was introduced more than 30 years ago. It is only rarely used these

>days and it does not exist under Windows XP. Under Windows XP you have the

>Console (or Command Prompt), much like the console under non-Microsoft OSs.

>Although it's black and character based, it has very little in common with

>DOS.




I knew you were going to jump in and say that. You *NEVER* miss an

opportunity to point out to people using the word DOS that DOS no longer

exists.



Don (e-mail link at home page bottom).
 
"Don Wiss" wrote in message

news:il6aq5hrt9hkme5ndpvk98mc4c9sb7td6s@4ax.com...

> On Sat, 20 Mar 2010, "Pegasus [MVP]" wrote:

>

>>It might be appropriate to start by cleaning out some misunderstandings.

>>There is no such thing as a "DOS batch file". DOS is an operating system

>>that was introduced more than 30 years ago. It is only rarely used these

>>days and it does not exist under Windows XP. Under Windows XP you have the

>>Console (or Command Prompt), much like the console under non-Microsoft

>>OSs.

>>Although it's black and character based, it has very little in common with

>>DOS.


>

> I knew you were going to jump in and say that. You *NEVER* miss an

> opportunity to point out to people using the word DOS that DOS no longer

> exists.

>

> Don (e-mail link at home page bottom).




Yes, you're right, and by the same token I never miss an opportunity to

point out that the earth was not created 6781 years ago (or whatever that

number might be). Both claims are flawed and lead to erroneous conclusions.

At the same time I spent ten minutes to give the OP a workable solution to

his problem.
 
On Sat, 20 Mar 2010, "Pegasus [MVP]" wrote:



>Don Wiss wrote:

>> I knew you were going to jump in and say that. You *NEVER* miss an

>> opportunity to point out to people using the word DOS that DOS no longer

>> exists.


>

>Yes, you're right, and by the same token I never miss an opportunity to

>point out that the earth was not created 6781 years ago (or whatever that

>number might be). Both claims are flawed and lead to erroneous conclusions.

>At the same time I spent ten minutes to give the OP a workable solution to

>his problem.




Except in this case we can assume that the OP knows that the original DOS

is now gone, and was just using DOS as slang for the command prompt. In

contrast, the people that believe the earth is only "6781" years old really

do believe it and nothing you say will convince them otherwise. And you

can't even argue with them. For example. You point out that objects can be

dated to much older. They will respond that god is so great he can make

things appear old. How do you respond to that?



Don (e-mail link at home page bottom).
 
"Don Wiss" wrote in message

news:f1aaq5t42ceba7f2ku0v2b563352tbduar@4ax.com...

> On Sat, 20 Mar 2010, "Pegasus [MVP]" wrote:

>

>>Don Wiss wrote:

>>> I knew you were going to jump in and say that. You *NEVER* miss an

>>> opportunity to point out to people using the word DOS that DOS no longer

>>> exists.


>>

>>Yes, you're right, and by the same token I never miss an opportunity to

>>point out that the earth was not created 6781 years ago (or whatever that

>>number might be). Both claims are flawed and lead to erroneous

>>conclusions.

>>At the same time I spent ten minutes to give the OP a workable solution to

>>his problem.


>

> Except in this case we can assume that the OP knows that the original DOS

> is now gone, and was just using DOS as slang for the command prompt. In

> contrast, the people that believe the earth is only "6781" years old

> really

> do believe it and nothing you say will convince them otherwise. And you

> can't even argue with them. For example. You point out that objects can be

> dated to much older. They will respond that god is so great he can make

> things appear old. How do you respond to that?

>

> Don (e-mail link at home page bottom).




I try to give the OP a solution that works.
 
Hi, see comments inline below...



"Pegasus [MVP]" wrote in message

news:esxi0JCyKHA.5936@TK2MSFTNGP04.phx.gbl...

>

>

> "Scott Bass" wrote in

> message news:eiTDo19xKHA.2012@TK2MSFTNGP04.phx.gbl...

>> Hi,

>>

>> I'm not sure this is the correct newsgroup - if not, can you please

>> suggest

>> the appropriate one for a DOS batch question? Thanks...

>>

>> I'd love to code my problem in VBS, PowerShell, Perl, Python, Ruby, ...

>> anything but DOS. Since I can't, here's my problem: (Note: I can't

>> install ANY additional s/w on the end user's machines and can't use VBS)

>>

>> I've got a config file for an application that looks like:

>>

>> -log "C:\Some\Path To\My Config\File\config.cfg"

>>

>> I have to parse this file, extracting the value for the logs location

>> into a

>> variable, in order to search the generated logs after the application

>> executes. The problem comes from the spaces in the file path.

>>

>> I've got this code (with lots of debugging stub statements):

>>

>> setlocal

>>

>> FOR /F "usebackq tokens=2-5* delims= " %%a IN (`findstr /i /c:-log

>> "%config%"`) DO (

>> echo A %%a

>> echo B %%b

>> echo C %%c

>> echo D %%d

>> echo E %%e

>>

>> if defined A echo A IS DEFINED

>> if defined B echo B IS DEFINED

>> if defined C echo C IS DEFINED

>> if defined D echo D IS DEFINED

>> if defined E echo E IS DEFINED

>>

>> if not dummy==dummy%%a echo A IS NOT BLANK

>> if not dummy==dummy%%b echo B IS NOT BLANK

>> if not dummy==dummy%%c echo C IS NOT BLANK

>> if not dummy==dummy%%d echo D IS NOT BLANK

>> if not dummy==dummy%%e echo E IS NOT BLANK

>>

>> if not dummy==dummy%%a set logs=%%a

>> if not dummy==dummy%%b set logs=%%logs %%b

>> if not dummy==dummy%%c set logs=%%logs %%c

>> if not dummy==dummy%%d set logs=%%logs %%d

>> if not dummy==dummy%%e set logs=%%logs %%e

>>

>> echo %%logs

>> )

>>

>> echo %%logs

>>

>> It's not ideal, since I could (in theory) have a path with more than 5

>> space

>> separated tokens. But not likely, so I can live with this. I have a

>> feeling the problem could be due to immediate vs. delayed variable

>> resolution. And I may be using %%var vs. %var% incorrectly.

>>

>> Ideally, I'd like to retrieve the line from the log, and do a search and

>> replace on "-log" (s/-log//g in say Perl or vi on Unix). But I can't see

>> how to do this in a DOS batch file. If there is a way to do a search and

>> replace in DOS OOTB, that would be great.

>>

>> Any ideas how to parse the above to return the results equivalent to:

>>

>> set logs="C:\Some\Path To\My Config\File\config.cfg"

>>

>> Thanks,

>> Scott


>

> It might be appropriate to start by cleaning out some misunderstandings.

> There is no such thing as a "DOS batch file". DOS is an operating system

> that was introduced more than 30 years ago. It is only rarely used these

> days and it does not exist under Windows XP. Under Windows XP you have the

> Console (or Command Prompt), much like the console under non-Microsoft

> OSs. Although it's black and character based, it has very little in common

> with DOS.




Thanks for the clarification (I'm not being sarcastic). I do want to use

correct terminology.



Rhetorical questions not requiring a reply: Wasn't Windows 95 just slapped

on top of DOS? Does Windows XP still have a boot option to boot to DOS

mode? Don't some low level disk utilities require a Windows machine to boot

into DOS mode?



>

> About your batch file - how about something like the code below. Note that

> most of its instructions would fail under DOS. And by the way - if you

> don't like coding batch files, what prevents you from writing a small VB

> Script file? Cscript.exe is native to all current flavours of Windows and

> the code would be quite trivial.




Yeah, I'm re-thinking this. I'm no guru in VB Script, but have written a

few, and Google is my friend (plus other microsoft.public... newsgroups).

The issue is that no one else in my department knows VB Script, so the

script would be difficult to maintain or clone/modify. A minor issue is

that the default windows host engine (if that's the right term) can vary

between cscript and wscript across user's machines. I think (???) if I used

some wscript commands, such as displaying a message dialog, and the script

was running under cscript, that it would fail.



I wish there was a way for a script to force itself to run under a

particular engine...a bit like #!/bin/sh, #!/bin/ksh, or #!/bin/bash under

Unix, where the processing shell is determined by the specially formatted

comment in the first line.



> @echo off

> set Line=x

> for /F "delims=" %%a in ('type "d:\temp\test.txt" ^| find /i "-log "') do

> set Line=%%a

> if x==%Line% goto :eof

> set Line=%Line:-log=%

> for /F "delims=" %%a in ('echo %Line%') do set LogPath=%%a

> echo LogPath=%LogPath%




Thanks for this, much appreciated.



Finally, I did read with some amusement the rest of the messages in this

thread. Man, I'm so flat out with work, I'd never have time to get into

such dialogue! Why not just add him into your kill file, or just ignore his

messages? Someone gets oh, one chance at being negative with me before

they're blocked and I never hear from them again :-)



Again, thanks for the help.



Cheers,

Scott
 
I'm still having problems getting this to work. Here is my test

script:



set config=C:\Temp\config.cfg



set Line=###

for /F "delims=" %%A in ('type "%config%" ^| find /i "-log "') do set

Line=%%A

echo %Line%



if ###==%Line% (

echo ERROR: Unable to determine logs directory from config file.

goto debug

)



set Line=%Line:-log=%

for /F "delims=" %%A in ('echo %Line%') do set LogPath=%%~A



:debug

echo LINE=%Line%

echo LOGPATH=%LogPath%



In C:\Temp\config.cfg, enter (exactly as typed):



-LOG "C:\Temp\Some Directory Path\With Spaces\So Path\Is Quoted"



To cause the first bit to fail, just replace -LOG with -xLOG in the

config file.



No matter how I code this (replace ### with x, etc), the if statement

always evaluates to true.



I want the final LogPath to be C:\Temp\Some Directory Path\With Spaces

\So Path\Is Quoted (without double quotes)



Thanks,

Scott
 
"Scott Bass" wrote:



> I'm still having problems getting this to work. Here is my test

> script:

>

> set config=C:\Temp\config.cfg

>

> set Line=###

> for /F "delims=" %%A in ('type "%config%" ^| find /i "-log "') do set

> Line=%%A

> echo %Line%

>

> if ###==%Line% (

> echo ERROR: Unable to determine logs directory from config file.

> goto debug

> )

>

> set Line=%Line:-log=%

> for /F "delims=" %%A in ('echo %Line%') do set LogPath=%%~A

>

> :debug

> echo LINE=%Line%

> echo LOGPATH=%LogPath%

>

> In C:\Temp\config.cfg, enter (exactly as typed):

>

> -LOG "C:\Temp\Some Directory Path\With Spaces\So Path\Is Quoted"

>

> To cause the first bit to fail, just replace -LOG with -xLOG in the

> config file.

>

> No matter how I code this (replace ### with x, etc), the if statement

> always evaluates to true.

>

> I want the final LogPath to be C:\Temp\Some Directory Path\With Spaces

> \So Path\Is Quoted (without double quotes)

>

> Thanks,

> Scott




Welcome to the wonderful world of advanced batch files. They are a bit of a

black art - you often do not know in advance what to expect and you need to

experiment until you get it just right. This is why I prefer VB Scripts, in

particular when I need a robust solution.

I do not know why your batch file should fail the "if" statement. Here is a

modified version that works on my machine.

set config=d:\Temp\test.txt

set Line=###

for /F "delims=" %%A in ('type "%config%" ^| find /i "-log "') do set Line=%%A

echo %Line%



if ###==%Line% goto debug

set Line=%Line:-log=%

for /F "delims=" %%A in ('echo %Line%') do set LogPath=%%~A

echo LOGPATH=%LogPath%

goto :eof



:debug

echo ERROR: Unable to determine logs directory from config file.

echo LINE=%Line%

echo LOGPATH=%LogPath%
 
Here is a robust hybrid solution that is not subject to any black magic:

@echo off

set sKey="-Log "

set sLogname="d:\temp\test.txt"

set Scr="%temp%\TempVBS.vbs"

set VB=echo^>^>%Scr%

cd 1>nul 2>%Scr%

%VB% Set oFSO = CreateObject("Scripting.FileSystemObject")

%VB% Set oFile = oFSO.OpenTextFile(%sLogName%)

%VB% bfound = False

%VB% While Not oFile.AtEndOfStream And Not bfound

%VB% sLine = oFile.ReadLine

%VB% If InStr(1, sLine, %sKey%, 1) = 1 Then

%VB% sLine = Trim(Mid(sLine, 5))

%VB% bfound = True

%VB% End If

%VB% Wend

%VB% oFile.Close

%VB% If bfound _

%VB% Then WScript.Echo sLine _

%VB% Else WScript.Echo "Keyword", %sKey%, "not found"

cscript //nologo %Scr%

del %Scr%
 
For future reference, a more specific place to ask questions about

advanced Windows batch scripting is
 
Scott Bass wrote:

>

> Rhetorical questions not requiring a reply: Wasn't Windows 95 just

> slapped on top of DOS?




Yes, as was Windows 1, Win 2, Win3, Win 98 and their variants.





> Does Windows XP still have a boot option to

> boot to DOS mode?




No. In spite of the name, Win XP is a continuation of the Windows NT

dynasty, not the plain Windows line.



> Don't some low level disk utilities require a

> Windows machine to boot into DOS mode?




None that come with XP.
 
Back
Top