Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Running Command Based on grep Output in Batch

1,471 views
Skip to first unread message

No I'm Spartacus

unread,
Jun 29, 2006, 11:03:53 AM6/29/06
to
Hi,

I was trying to write a batch file for Windows XP, but I've become
stuck, so I was looking for some help. I have a backup being run on a
small Windows network. This backup produces a log file. Because I
don't sit at the PC that the log file is produced on (and thus can't
check it manually myself after each backup), I wanted to write a batch
file to grep (Win32 port of GNU grep) the log for any errors, and if
so, pop up a message on screen asking the operator to inform me. I
have now got the grep part working fine, but I can't work out a way to
have a pop up message. My first thought was the have a .txt file with
the message in it (say msg.txt), and to run the command 'edit
msg.txt'. This would pop up the message, but the problem is, you can
either run the edit command, or you don't - I could see no way to pipe
the grep output to anything that would only run the edit command if
the grep was a certain value.

Anyway, all I really have at this stage is a working grep statement.
I've found that if I use grep -c, then the count for a 'no error' log
is 2, and for a log with errors, it's a number other than 2 (I thought
a count with -c would be easier to work with than the actual error
text from the log). I did think of piping this to some sort of IF
command (so 'IF 2, do nothing, IF other than 2, run edit msg.txt' sort
of thing), but I couldn't get this to work.

So, if anyone can help me out with this, it would be appreciated.
--

Regards,

Spartacus

foxidrive

unread,
Jun 29, 2006, 11:25:06 AM6/29/06
to

How about

@echo off
find /i "error" "logfile.txt">nul
if not errorlevel 1 echo please contact spartacus
pause


You can also use findstr to filter further, even using regexp, and wrap it
in a for /f in do command to parse certain words out - if the log file
allows that.

A refinement might be to send yourself an email using BLAT or similar with
the log/excerpt attached.

No I'm Spartacus

unread,
Jun 30, 2006, 7:17:00 AM6/30/06
to
On Fri, 30 Jun 2006 01:25:06 +1000, foxidrive <woo...@gotcha.invalid>
wrote:

Hi foxidrive,

I had to post this query from home, as no access to do it at work, but
when I read your reply, I immediately thought it would work, and I
also thought it was pretty clever, and a far simpler way of doing it
than what I was thinking about. However, I could not get it to work
when I went to work earlier today. The batch file runs to completion
without errors, but no message is ever displayed on screen. I could
only guess that either find (I also tried findstr) does not produce a
0 or 1 as an errorcode when it completes (and for which the if
statement relies on), or that the echo part of the if statement was
not working.

I basically used grep for the text part because the log file produces
the errors as a non zero character in a column - there's no 'this
error occurred' line of text. Also, I produce one log file per PC, so
there are 5 log files to run the 'pop up message about error in log'
batch file - I would assume that I would need the two lines of your
suggestion repeated for each log file? ie
line 1 log1.txt
line 2 log1.txt
line 1 log2.txt
line 2 log2.txt
etc

Lastly, because there is no error text, just a non zero (and it can be
any number), in a couple of columns to indicate an error (log is
produced by Robocopy), I decided to use grep -c. Because that non zero
number can be anything, I couldn't see how to test for that number
using whatever was going to pop up the error message. At least with
grep -c, it seemed that if there were no errors, the count was a 2 for
each log file, and if there were errors - well, I haven't had any, so
I have no idea what is prduced by grep -c - but I am assuming it is
anything other than 2. So the -c option seemed to give me some more
consistency - if you never know what the error is going to be, you
can't really use another command to pop up a message if it occurs.

Anyway, I don't really know where to go from here. As I mentioned,
your echo statement is a far simpler way of doing what I wanted than
the direction my idea's were going in. The only problem I forsaw with
it is that the pause statement is not good for a batch running in
unattended mode - but without the pause, I don't see that the message
would stay up on screen for anyone to read it. That is a bit of a
problem - the batch has to run in unattended mode, and only pop up
when there is an error, not all the time.
--

Regards,

Spartacus

Marcus Red

unread,
Jun 30, 2006, 7:39:37 AM6/30/06
to
How about something like:

@echo off
grep -c syntax? >errcnt.txt
find "2" errcnt.txt>nul


if not errorlevel 1 echo please contact spartacus

if not errorlevel 1 pause
del errcnt.txt

foxidrive

unread,
Jun 30, 2006, 8:25:04 AM6/30/06
to
>> Lastly, because there is no error text, just a non zero (and it can be
>> any number), in a couple of columns to indicate an error (log is
>> produced by Robocopy), I decided to use grep -c. Because that non zero
>> number can be anything, I couldn't see how to test for that number

It'd be good to see a snippet of robocopy log with a couple of errors, to
formulate a solution. The there are leading columns with the error numbers
that remain in a consistant format then it's easy to parse out the numeral
and compare it with "if foo GTR 2" some command.


>> The only problem I forsaw with
>> it is that the pause statement is not good for a batch running in
>> unattended mode - but without the pause, I don't see that the message
>> would stay up on screen for anyone to read it.

Instead of pause, use sleep from the resource kit, or this to wait for 15
seconds (16-1)

ping -n 16 127.0.0.1 >nul

No I'm Spartacus

unread,
Jun 30, 2006, 11:57:11 AM6/30/06
to
On Fri, 30 Jun 2006 22:25:04 +1000, foxidrive <woo...@gotcha.invalid>
wrote:

Hi foxidrive,

Yep, I've attached the full log from one of the PC's to this post. I
have the switches in Robocopy set to only show the summary, so it
should be the same format every single time, regardless of whether
there was an error or not. Basically, what I want to do is if (after
the Robocopy batch runs - it at least runs perfectly ;-), pop up a
message if there is anything other than a zero in the 'mismatch' or
'failed' columns (see attached file).

Just for info (grepping in the first place may even be the wrong way
to go about this, it was the only thing I could think of at the time,
I had no other reason for doing it that way, so I'm open to any idea's
as how to do it differently), the grep statement for each PC log is:
grep -E -c "(Dirs|Files)" pc1.txt | grep -Ev "0 +0 +[0-9]+$" >
grep_count_pc1.txt
There are 5 lines like this in the batch file, one after the other,
the only thing that changes for each line is PC2 replaces PC1 in the
second line, PC3 replaces PC2 in the third line etc

I also bought the batch files home from work today to work on them, to
see whether I could get them to work. I made an interesting discovery
in doing so - it looks like grep -c is always 2, regardless of if
there is an error in the log or not. That throws out my idea of using
-c in the first place. Oh well.
--

Regards,

Spartacus

=ybegin line=128 size=491 name=pc2.txt
7474WWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWW7474JJJJJJJJJJJJJJJJ~™ž‹–JJJJm™š“ ŽJJJ}•“šš ŽJ
Jw“ —‹ž ’JJJJpksvonJJJJo¢žœ‹ 74JJJJJn“œ JdJJJJJJJJ_`JJJJJJJJJZJJJJJJJJ_`JJJJJJJJJZJJJJJJJJJZJJJJJJJ\]Z74JJJJp“– JdJJJJJJ[]\aJJJ
JJJJJJZJJJJJJ[]\aJJJJJJJJJZJJJJJJJJJZJJJJJJJ\]Z74JJJJl£ž JdJJJaaXabJ—JJJJJJJJJZJJJaaXabJ—JJJJJJJJJZJJJJJJJJJZJJJ[[]XbJ•74JJJJ~“
— JdJJJZdZZdZZJJJZdZZdZZJJJJJJJJJJJJJJJJJJJJJJJZdZZdZZJJJZdZZdZZ7474JJJJo˜Ž ŽJdJpœ“JtŸ˜J]ZJ[adZZd\aJ\ZZ`74
=yend size=491 crc32=e90ea565

No I'm Spartacus

unread,
Jun 30, 2006, 12:00:54 PM6/30/06
to

Hi Marcus,

Thanks for the suggestion. Please see my other reply to foxidrive (the
one where I've attached one of the logs). I've found out that grep -c
always produces 2 for these logs, regardless of whether there is an
error or not. That throws a bit of a spanner into my works :-(
--

Regards,

Spartacus

No I'm Spartacus

unread,
Jun 30, 2006, 12:52:09 PM6/30/06
to

Hi again everyone,

Well, after playing a bit more with it, I think I almost have
something. It is very long winded, but I think it works, except for
one thing. The batch is running as a scheduled task, and that means
the CMD window closes once it has finished. However, in this case,
because I need a pause statement to keep the window open to show that
the log has errors, that needs a bit of thinking. I've pasted my
current batch below (paths have been adjusted to fit in with my home
PC structure, I will adjust those back when I take it back to work. My
problem is in :FIND6-2, fourth line, where the batch file ignores the
GOTO :WAIT part. I put this in there so that if there were any errors,
the pause would only be run then - otherwise, no errors, no pause (so
it could still run unattended mostly). I figure that the if statement
can only have one line in the else part. There are two :FIND per PC
because the error can either be in the DIRS line of the log, or the
FILES line of the log. Anyway, here it is:

@ECHO OFF

ECHO ========================
ECHO.
ECHO Backup Log v1.0 for Windows XP (27 JUNE 2006)
ECHO.
ECHO Runs Win32 GNU grep on the Robocopy logs produced by
ECHO c:\Backup.bat and looks for any non-zero entries in
ECHO either the Mismatch or FAILED columns of the job
ECHO summary. If there are none, no further action is
ECHO taken. If there are Mismatched or Failed entries,
ECHO then this batch file makes a window pop up on this PC
ECHO to alert the operator, so they can alert me. This is
ECHO scheduled to run through Windows Scheduler at 20 minutes
ECHO after each run of Backup.bat (Backup.bat is currently
ECHO scheduled to run every hour from 9am to 5pm, and
ECHO finally at 7pm).
ECHO.
ECHO Changelog: v1.0 27 JUNE 2006 Initial version.
ECHO.
ECHO Written by Spartacus
ECHO.
ECHO ========================
ECHO.

:START
C:
cd c:\TempFiles\Batch\Program Files\Robocopy
grep -E "(Dirs|Files)" pc1.txt | grep -Ev "0 +0 +[0-9]+$" >
grep_count_pc1.txt
grep -E "(Dirs|Files)" pc2.txt | grep -Ev "0 +0 +[0-9]+$" >
grep_count_pc2.txt
grep -E "(Dirs|Files)" pc3.txt | grep -Ev "0 +0 +[0-9]+$" >
grep_count_pc3.txt
grep -E "(Dirs|Files)" pc4.txt | grep -Ev "0 +0 +[0-9]+$" >
grep_count_pc4.txt
grep -E "(Dirs|Files)" pc6.txt | grep -Ev "0 +0 +[0-9]+$" >
grep_count_pc6.txt
GOTO :FIND1-1

:FIND1-1
find /i "Dirs" "c:\TempFiles\Batch\Program
Files\Robocopy\grep_count_pc1.txt">nul
if not errorlevel 1 (
echo *** Error in Backup - PC1 Dirs - Please Inform Chris! ***
) else (
GOTO :FIND1-2
)

:FIND1-2
find /i "Files" "c:\TempFiles\Batch\Program
Files\Robocopy\grep_count_pc1.txt">nul
if not errorlevel 1 (
echo *** Error in Backup - PC1 Files - Please Inform Chris! ***
) else (
GOTO :FIND2-1
)

:FIND2-1
find /i "Dirs" "c:\TempFiles\Batch\Program
Files\Robocopy\grep_count_pc2.txt">nul
if not errorlevel 1 (
echo *** Error in Backup - PC2 Dirs - Please Inform Chris! ***
) else (
GOTO :FIND2-2
)

:FIND2-2
find /i "Files" "c:\TempFiles\Batch\Program
Files\Robocopy\grep_count_pc2.txt">nul
if not errorlevel 1 (
echo *** Error in Backup - PC2 Files - Please Inform Chris! ***
) else (
GOTO :FIND3-1
)

:FIND3-1
find /i "Dirs" "c:\TempFiles\Batch\Program
Files\Robocopy\grep_count_pc3.txt">nul
if not errorlevel 1 (
echo *** Error in Backup - PC3 Dirs - Please Inform Chris! ***
) else (
GOTO :FIND3-2
)

:FIND3-2
find /i "Files" "c:\TempFiles\Batch\Program
Files\Robocopy\grep_count_pc3.txt">nul
if not errorlevel 1 (
echo *** Error in Backup - PC3 Files - Please Inform Chris! ***
) else (
GOTO :FIND4-1
)

:FIND4-1
find /i "Dirs" "c:\TempFiles\Batch\Program
Files\Robocopy\grep_count_pc4.txt">nul
if not errorlevel 1 (
echo *** Error in Backup - PC4 Dirs - Please Inform Chris! ***
) else (
GOTO :FIND4-2
)

:FIND4-2
find /i "Files" "c:\TempFiles\Batch\Program
Files\Robocopy\grep_count_pc4.txt">nul
if not errorlevel 1 (
echo *** Error in Backup - PC4 Files - Please Inform Chris! ***
) else (
GOTO :FIND6-1
)

:FIND6-1
find /i "Dirs" "c:\TempFiles\Batch\Program
Files\Robocopy\grep_count_pc6.txt">nul
if not errorlevel 1 (
echo *** Error in Backup - PC6 Dirs - Please Inform Chris! ***
) else (
GOTO :FIND6-2
)

:FIND6-2
find /i "Files" "c:\TempFiles\Batch\Program
Files\Robocopy\grep_count_pc6.txt">nul
if not errorlevel 1 (
echo *** Error in Backup - PC6 Files - Please Inform Chris! ***
GOTO :WAIT
) else (
GOTO :END
)

:WAIT
pause
GOTO :END

:END
cd c:\TempFiles\Batch\Root

Very long winded, but it does work except for the pause part (as I
mentioned above, it ignores the GOTO :WAIT line in :FIND6-2). At the
moment, the window just closes (though it does display the 'error in
log' message for the millisecond that it is open). So far it seems
that I can either have the file pause (and make it useless for
unattended mode), or flash up the 'error in log' message a millisecond
before the window closes (thus also making it useless to even run).
--

Regards,

Spartacus

foxidrive

unread,
Jul 1, 2006, 12:39:44 AM7/1/06
to
On Fri, 30 Jun 2006 16:52:09 GMT, No I'm Spartacus wrote:

> Well, after playing a bit more with it, I think I almost have
> something. It is very long winded, but I think it works, except for
> one thing. The batch is running as a scheduled task, and that means
> the CMD window closes once it has finished. However, in this case,
> because I need a pause statement to keep the window open to show that
> the log has errors, that needs a bit of thinking.

This works here, though it only tests for a numeral greater than 0 in the
FAILED column - was that the aim?

You could use BLAT and send yourself an email to eliminate the need for
user intervention, if email is available.

@echo off
setlocal
set errorflag=0
for %%a in (pc1 pc2 pc3 pc4 pc6) do (
for /f "tokens=7" %%b in (
'findstr /c:"Dirs :" /c:"Files :" "q:\%%a.txt"'
) do (
if %%b GTR 0 (
echo *** Error in Backup - %%a Files - Please Inform Chris! ***
set errorflag=1
)
)
)
if "%errorflag%"=="1" pause

No I'm Spartacus

unread,
Jul 1, 2006, 11:07:25 AM7/1/06
to
On Sat, 1 Jul 2006 14:39:44 +1000, foxidrive <woo...@gotcha.invalid>
wrote:

Hi foxidrive,

No, it should test for a greater than zero in either the Mismatched or
Failed columns, on either the Dirs or the Files line. It's a
stand-alone system that the backup is done on, and the PC I use is not
connected to that system in any way - but you're right. If I could
have just emailed myself the files each hour, that would have sufficed
(though after a few days, I would have probably got sick of checking
them and wanted to find an automated way anyway). The code you put in
above, does that go in each :FIND? Like in :FIND1-1, then paste
another copy in :FIND1-2, :FIND2-1 etc etc?
--

Regards,

Spartacus

foxidrive

unread,
Jul 1, 2006, 11:34:20 AM7/1/06
to
On Sat, 01 Jul 2006 15:07:25 GMT, No I'm Spartacus wrote:

>>This works here, though it only tests for a numeral greater than 0 in the
>>FAILED column - was that the aim?

> No, it should test for a greater than zero in either the Mismatched or


> Failed columns, on either the Dirs or the Files line.

This does that here. Change q:\ to your path for the log files.

@echo off
setlocal EnableDelayedExpansion


set errorflag=0
for %%a in (pc1 pc2 pc3 pc4 pc6) do (

for /f "tokens=6,7" %%b in (


'findstr /c:"Dirs :" /c:"Files :" "q:\%%a.txt"') do (

if %%b GTR 0 set flag=1
if %%c GTR 0 set flag=1
if "!flag!"=="1" (


echo *** Error in Backup - %%a Files - Please Inform Chris! ***
set errorflag=1
)

set flag=0


)
)
if "%errorflag%"=="1" pause

> It's a


> stand-alone system that the backup is done on, and the PC I use is not
> connected to that system in any way - but you're right. If I could
> have just emailed myself the files each hour

I meant to only email the files if there was an error, and with the files
that contain the error, but that point is moot.

> The code you put in
> above, does that go in each :FIND? Like in :FIND1-1, then paste
> another copy in :FIND1-2, :FIND2-1 etc etc?

Me no capische. As it stands it'll check the pc1 pc2 pc3 pc4 pc6 (.txt)
files if you enter the path to them, in place of Q:\

No I'm Spartacus

unread,
Jul 2, 2006, 2:06:17 AM7/2/06
to
On Sun, 2 Jul 2006 01:34:20 +1000, foxidrive <woo...@gotcha.invalid>
wrote:

Hi foxidrive,

Excellent! That works nicely, thanks very much fot that :-) And it's a
lot less long winded then what I had pasted in as my last attempt too!
--

Regards,

Spartacus

No I'm Spartacus

unread,
Jul 9, 2006, 3:56:41 AM7/9/06
to

Hi again,

I added a couple of lines to this, to send a net send message to all
the other PC's on the network (just in case the normal operator of the
PC that the error message is displayed on is away for the day or
whatever, and the message is missed). What I'm trying to do now is
this: the backup that could error runs once per hour. If an error
occurs, and the Robocopy log is not checked by someone before the next
hour is up, the log with the error in it will be overwritten. So, what
I was wanting to do was if there was an error, to someghow backup the
log to a separate folder, so if the next backup runs, there will
always be a copy of the error log in the other folder. Problem is, I
don't have many idea's on how to do it. I thought maybe a simple copy
statement after the error message display code, but how would I tell
it to randomise the name of the log it is copying? ie if there is an
error, and it copies pc1.txt to another folder, then - in an hour -
when the next backup runs, it could see another error, and copy the
pc1.txt to the other folder again, thus overwriting the first copy.
Being able to put the date and time at the end of the log filename
would be ideal, but I tried this once with another backup batch file,
and I don't think it is actually possible.
--

Regards,

Spartacus

foxidrive

unread,
Jul 9, 2006, 6:02:00 AM7/9/06
to
On Sun, 09 Jul 2006 07:56:41 GMT, No I'm Spartacus wrote:

> Being able to put the date and time at the end of the log filename
> would be ideal, but I tried this once with another backup batch file,
> and I don't think it is actually possible.

You can simply rename the log file and append the date and time.
Getting the date and time is location dependant, but is one of the most FAQ
in the group. If you can paste the output of

echo "%date%"
echo "%time%"

someone can give you specifics for your particular servers locale setting.

0 new messages