I have a couple of batch files that output to the screen and also to a text
file.
This is done with two seperate commands each time.
e.g.
echo Processing %1
echo Processing %1 >result.txt
Is there a neat way of echoing to screen and file in one go?
Of course subsequent echos to file need to append:
echo Done processing %1
echo Done processing %1 >>result.txt
A TEE filter is one way. Here are some batch file TEE filter idea but
you can find TEE filters on the net too. Not all are compatible with NT
versions fo Windows.
:: tee.bat - idea from Joachim Hofmann
:: Syntax: TEE logfilename.log dos_command_to_capture
:: Example: tee logfile.log COPY "c:\myfolder\*.txt" "d:\backup\"
:: tee "My log.log" dir c:\*.sys /b
@ECHO OFF
set logfile="%~1"
if exist %logfile% del %logfile%
set "var=%*"
set "var=%var:*.log =%"
set "var=%var:*.log" =%"
for /F "tokens=1* delims=]" %%a IN (
'%var% 2^>^&1^|find /v /n ""'
) DO (
set /p"=%%b"<nul
echo.
set /p"=%%b"<nul>>%logfile%
echo.>>%logfile%
)
pause
From Tom Lavadas
@echo off
> TFILTER.VBS echo. sLogName="Logfile.log" ' default name
>>TFILTER.VBS echo. if WSH.Arguments.Count^>0 then sLogName=WSH.Arguments(0)
>>TFILTER.VBS echo. with CreateObject("Scripting.FileSystemObject")_
>>TFILTER.VBS echo. .OpenTextFile(sLogName, 8, true)
>>TFILTER.VBS echo. .WriteLine Now
>>TFILTER.VBS echo. Do Until WSH.StdIn.AtEndOfStream
>>TFILTER.VBS echo. str = WSH.StdIn.ReadLine
>>TFILTER.VBS echo. wsh.echo str : .WriteLine str
>>TFILTER.VBS echo. Loop
>>TFILTER.VBS echo. end with ' FSO
(echo === Started ====
copy *.bat "c:\folder" /y
echo ====text here=== )|cscript //nologo TFILTER.VBS MyLogFile.txt
del TFILTER.VBS
From William Allan:
Pipes in Windows NT/2000/XP operate to memory, and don't wait for
the completion of the input-side process. This means you can pipe
the output of your Batch file to a T-filter created in WSH with a
simple VBScript file. For example, create the following T-filter in
a plain text VBS file:
Lines that don't begin with two spaces have wrapped accidentally
====Begin cut-and-paste (omit this line)
Set StdIn = WScript.StdIn
Set StdOut = WScript.StdOut
Set Args=WScript.Arguments
LogFile=Args(0)
Set fso = CreateObject("Scripting.FileSystemObject")
Set LogFile= fso.CreateTextFile(Args(0))
LogFile.WriteLine Date & " " & Time
Do While Not StdIn.AtEndOfStream
str = StdIn.ReadLine
StdOut.WriteLine str
LogFile.WriteLine str
Loop
LogFile.Close
====End cut-and-paste (omit this line)
For study/demo use. Cut-and-paste as VBScript (.VBS) text file.
Batch file troubleshooting: http://www.allenware.com/find?UsualSuspects
With that file cut-and-paste as, say TFILTER.VBS, run your
Batch file with a pipe to the filter executed with CSCRIPT and
add the logfile name you require as a parameter.
Something like this:
MyBatchFile.bat | cscript//nologo TFILTER.VBS MyLogFile.txt
The output of the Batch file is displayed line-by-line and
simultaneously captured to MyLogFile.txt line-by-line.
Note: You must execute the TFILTER.VBS with CSCRIPT and
not WSCRIPT (STDIN and STDOUT are not available via WSCRIPT).
This technique avoids the use of third-party utilities. You could
create the TFILTER.VBS initially on-the-fly in the Batch file, and
delete it when the Batch file finishes. If you do, remember the
need to escape & characters with ^, thus: ^& when ECHO-ing them.
===[paste]===
--
Regards,
Mic
94} Can I send the script's output both to the screen and a log file?
http://www.netikka.net/tsneti/info/tscmd094.htm
All the best, Timo
--
Prof. Timo Salmi mailto:t...@uwasa.fi ftp & http://garbo.uwasa.fi/
Hpage: http://www.uwasa.fi/laskentatoimi/english/personnel/salmitimo/
Department of Accounting and Finance, University of Vaasa, Finland
Useful CMD script tricks http://www.netikka.net/tsneti/info/tscmd.php
Thanks for the replies, they all look a bit more complex than what I was
looking for. I want to keep it simple, and all within a batch file.
Perhaps I'll just call a sub that outputs the text once to screen and once
to the file:
call :op Output text to display on screen and copy to file.
call :op Second line of output text.
.
.
.
goto :EOF
:op
echo %*
echo %* >> res.txt
goto :EOF
Use some of *tee.exe program. For example http://www.commandline.co.uk/mtee/
> Thanks for the replies, they all look a bit more complex than what I was
> looking for. I want to keep it simple, and all within a batch file.
>
> Perhaps I'll just call a sub that outputs the text once to screen and once
> to the file:
It is one option. Unfortunately, it is not always quite as simple as one
thinks, because there can be subtle file handle pitfalls in the
subroutine method. For more on that, you may wish to see
http://www.netikka.net/tsneti/info/tscmd094.htm#handle
> call :op Output text to display on screen and copy to file.
> call :op Second line of output text.
> .
> goto :EOF
>
> :op
> echo %*
> echo %* >> res.txt
> goto :EOF
All the best, Timo
I have a 'tee.cmd' in my old batch library on sourceforge. The
project is 'blip', short for 'Batch Library In Progress'.
Best regards,
John D.
>e.g.
Yes, it can be done in one line using the symbol &, I hope this
helps.
echo Processing %1 & echo Processing %1 >result.txt
That's an interesting article - I had no idea about the numerical characters
being mistaken for file handles - there isn't usually a requirement to
escape these when Echoing is there?
Perhaps I need to work out a way of replacing numbers with escaped numbers
within the subroutine...I don't want to have to remember to escape them
every time I call the sub.
Hmmm.... I wanted to avoid having to edit text twice (possibility of errors)
so that's not a solution for me this time.
Thanks anyway.
A solution for the end of line numbers issue is either leave a space
before the redirection characters (which is included in the output file)
echo %* >>res.txt
Or place the redirection at the start of the line.
>>res.txt echo %*
--
Regards,
Mic
>>> It is one option. Unfortunately, it is not always quite as simple as
>>> one thinks, because there can be subtle file handle pitfalls in the
>>> subroutine method. For more on that, you may wish to see
> A solution for the end of line numbers issue is either leave a space
> before the redirection characters (which is included in the output file)
> echo %* >>res.txt
> Or place the redirection at the start of the line.
> >>res.txt echo %*
Yes, true. Unfortunately, even that (better) solution breaks down with
some poison characters in the passed text like &
The batch-subroutine method of teeing simply is subject to pitfalls.
There is one robust method of echoing text characters though, Timo.
I believe that only % has issues with this and they will merely be
truncated and not cause an error.
@echo off
call :subroutine "%&!><?*|"
goto :eof
:subroutine
for /f "delims=" %%a in ("%~1") do >>file.txt echo %%a
--
Regards,
Mic
Good! I have incorporated the discussed into
http://www.netikka.net/tsneti/info/tscmd094.htm#handle
:subroutine
for /f "tokens=1*delims==" %%a in ('set $_') do echo %%b >> nee.txt
goto:eof
--------------8<----------------
That's good. As long as there are doubled percent characters and there
are no mismatched single percent characters, it's as robust as batch can
make it.
Just for the record Delayed expansion damages the ! and ^ characters in
the example.
@echo off
setlocal enabledelayedexpansion
Set "$_=%%&!><?*|^abc"
call :subroutine
goto :eof
:subroutine
for /f "tokens=1*delims==" %%a in ('set $_') do >>tee.txt echo %%b
goto:eof
--
Regards,
Mic
> That's good. As long as there are doubled percent characters and
> there are no mismatched single percent characters, it's as robust as
> batch can make it.
Regarding text which is entered into the script, percent signs must be
doubled by definition. Also, since the text is being entered by the
script writer it is probably known by that script writer if delayed
expansion is enabled and characters can be escaped if necessary ("^!",
"^^"). If it is not known if delayed expansion is enabled then it can be
tested by the script and special characters can be handled accordingly.
I've done this in some of the scripts I posted here and as I recall it
all characters could be correctly ECHOed.
Regarding text which is read from a file, percent signs need no special
treatment. I don't recall if "!" and "^" require special treatment.
Frank
setlocal enabledelayedexpansion
echo !#_!
pause
goto :eof
:subroutine
Set "$_=%~1"
for /f "tokens=1*delims==" %%a in ('set $_') do set "#_=%%b"
endlocal & set "#_=%#_:^^=^%" & goto:eof
----------------------------------8<------------------------
@echo off
Set "$h=%%&!><?*|^abc"
call :con $h
Call :fil $h
pause
goto :eof
:con
setlocal enabledelayedexpansion
echo !%~1!
endlocal & goto :eof
:fil
setlocal enabledelayedexpansion
echo:!%~1!>>tee.txt
endlocal & goto :eof
-----------------------8<------------------------------
That is exceptionally robust. well done.
Timo, please include this in your write up. Percent signs are the only
characters that need matched pairs and doubling.
This technique is worth noting because it could be used in other places.
@echo off
Set "$h=^^^!!!%%&!><?*|^abc!123"
call :tee $h
pause
goto :eof
:tee
setlocal enabledelayedexpansion
echo !%~1!
echo:!%~1!>>tee.txt
endlocal & goto :eof
--
Regards,
Mic
That is exceptionally robust. well done.
Timo, please include this in your write up. Percent signs are the only
characters that need matched pairs and doubling.
This technique is worth noting because it could be used in other places.
@echo off
Set "$h=^^^!!!%%&!><?*|^abc!123"
call :tee $h
pause
goto :eof
:tee
setlocal enabledelayedexpansion
echo !%~1!
echo:!%~1!>>tee.txt
endlocal & goto :eof
--
Regards,
Mic
>> :fil
>> setlocal enabledelayedexpansion
>> echo:!%~1!>>tee.txt
>> endlocal& goto :eof
> That is exceptionally robust. well done.
>
> Timo, please include this in your write up. Percent signs are the only
> characters that need matched pairs and doubling.
I've included links to this thread. While useful, interesting and
instructive, let's bear in mind the point that compared to using a "tee"
these solutions are, more or less, esoteric.
> While useful, interesting and
> instructive, let's bear in mind the point that compared to using a "tee"
> these solutions are, more or less, esoteric.
Yes, I would use a real tee filter... but that's the lure of a batch
file - to do what you can with a limited instruction set. :)
--
Regards,
Mic