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

remove duplicate entries from output

131 views
Skip to first unread message

ten.n...@virgin.net

unread,
May 3, 2005, 6:35:22 PM5/3/05
to
I have a WinXP cmd in which I need to remove duplicate entries from the output

for /f "tokens=1" %A in (lots of trivial stuff) do @echo %A
--- echo output ---
IEXPLORE.EXE
IEXPLORE.EXE
IEXPLORE.EXE
explorer.exe
explorer.exe
explorer.exe
------------------

What I want is
----- output -----
IEXPLORE.EXE
explorer.exe
------------------
Is there a simple routine to pass %A through in order to achieve that.
(prefereably without creating additional files).
The output will not necessarily be three of each, this can be variable.

Thanks in advance

billious

unread,
May 3, 2005, 7:09:12 PM5/3/05
to

<ten.n...@virgin.net> wrote in message
news:pan.2005.05.03...@virgin.net...

Presuming you're doing something other than just echo to the screen, try

for /f %%i in (nodup.txt) do echo %%i|find <nodup.rpt "%%i">nul &if
errorlevel 1 echo %%i>>nodup.rpt

where nodup.txt is a simulation of your (lots of trivial stuff) and
nodup.rpt is an established 0-byte file (or echo/>nodup.rpt if you can
handle a leading-empty-line)

Do you mean "no temporary files" or "just to the screen;no files at all" ?
(I'd hazard the latter is unachievable.)

HTH

...Bill


ten.n...@virgin.net

unread,
May 3, 2005, 7:45:22 PM5/3/05
to
On Wed, 04 May 2005 07:09:12 +0800, billious wrote:

> for /f %%i in (nodup.txt) do echo %%i|find <nodup.rpt "%%i">nul &if
> errorlevel 1 echo %%i>>nodup.rpt

Firstly thanks for the speedy response, and writing out to file will suffice.

----- output -----
for /F %i in (nodup.txt) do echo %i | find "%i" 0<nodup.rpt 1>nul & if errorlevel 1 echo %i 1>>nodup.rpt
The system cannot find the file nodup.txt.
------------------
I get this error even with the nodup.txt path specified.
The nodup.txt file is however created, what is the problem?

Ted Davis

unread,
May 3, 2005, 8:34:35 PM5/3/05
to

for /f %%i in (nodup.txt) do (echo %%i | awk "{if(!($0 in
A)){A[$0];print $0}})

where awk is gawk.exe from
<http://gnuwin32.sourceforge.net/packages/gawk.htm>. That is case
sensitive, but there's an easy way to normalize all input to one case
or the other. Anything that writes to STDOUT can go to the left of
the pipe.

--
T.E.D. (tda...@gearbox.maem.umr.edu)

Clay Calvert

unread,
May 3, 2005, 8:55:14 PM5/3/05
to

Since we don't know what the trivial stuff is, I used the output of
DIR sorted by date for this example.

@echo off
setlocal enabledelayedexpansion
(set line=)
for /f %%a in ('dir /od') do (
if %%a' NEQ !line!' echo %%a & set Line=%%a)

Clay Calvert
CCal...@Wanguru.com
Replace "W" with "L"

Timo Salmi

unread,
May 3, 2005, 11:24:55 PM5/3/05
to
Clay Calvert wrote:
> @echo off
> setlocal enabledelayedexpansion
> (set line=)
> for /f %%a in ('dir /od') do (
> if %%a' NEQ !line!' echo %%a & set Line=%%a)

Unfortunately, the method has two flaws.

Only the first word of ech line is echoed. That is easy to remedy:
for /f "delims=" %%a in ('dir') do (

The second one is the very common, familiar one. The empty lines are
dropped.

All the best, Timo

--
Prof. Timo Salmi ftp & http://garbo.uwasa.fi/ archives 193.166.120.5
Department of Accounting and Business Finance ; University of Vaasa
mailto:t...@uwasa.fi <http://www.uwasa.fi/~ts/> ; FIN-65101, Finland
Useful script files and tricks ftp://garbo.uwasa.fi/pc/link/tscmd.zip

Timo Salmi

unread,
May 3, 2005, 11:51:36 PM5/3/05
to
Ted Davis wrote:
> for /f %%i in (nodup.txt) do (echo %%i | awk "{if(!($0 in
> A)){A[$0];print $0}})

Unfortunately, also this solution is flawed. It has the same problems
as Clay's solution (see my relevant reply). Plus it has a syntax
error. The awk statement is missing the latter " needed.

If one takes the awk/sed route, the solution in Eric Pement's UNIX
one-liners is
sed '$!N; /^\(.*\)\n\1$/!P; D'
It has to be adapted for PC syntax first.

If one uses third party utilities, and is prepared to go beyond
awk/sed then a uniq.exe UNIX port is one option. Available e.g
from

878915 Oct 25 2003 ftp://garbo.uwasa.fi/win95/unix/UnxUpdates.zip
UnxUpdates.zip Updates for UnxUtils GNU utilities for native Win32

Timo Salmi

unread,
May 3, 2005, 11:58:54 PM5/3/05
to
billious wrote:
> for /f %%i in (nodup.txt) do echo %%i|find <nodup.rpt "%%i">nul &if
> errorlevel 1 echo %%i>>nodup.rpt

Same thing. Unfortunately the solution is flawed.
"The system cannot find the file specified."

Don't you good regulars test your solutions first. Not that this
is a free service, and improving what we all post is one of the
goals of the ng. Feedback about the intended solutions.

Timo Salmi

unread,
May 4, 2005, 12:16:19 AM5/4/05
to
ten.n...@virgin.net wrote:
> I have a WinXP cmd in which I need to remove duplicate entries from the output

Translating Eric Pement's solutions from his SED collection, his
option is
sed "$!N; /^\(.*\)\n\1$/!P; D" MyFile.txt

Tested. Works. :-)

The sed used in this case is from SED.EXE Stream Editor
20368 Oct 1 1991 ftp://garbo.uwasa.fi/pc/unix/sed15x.zip
HHSED executable, E.Raymond+D.Kirschbaum+H.Helman
(Note, I use these older versions)

But, also e.g. the already posted


878915 Oct 25 2003 ftp://garbo.uwasa.fi/win95/unix/UnxUpdates.zip
UnxUpdates.zip Updates for UnxUtils GNU utilities for native Win32

All the best, Timo

Timo Salmi

unread,
May 4, 2005, 1:21:45 AM5/4/05
to
Timo Salmi wrote:
(Two solution options for the upcoming FAQ item
97} I need to remove duplicate entries from the output or a file.)

A third option for the DRAFT

A Visual Basic Script (VBScript) aided solution demonstration
@echo off & setlocal enableextensions
::
:: Make a test file
for %%i in (1 2 2 2) do echo This is line %%i>>MyFile.txt
echo.>>MyFile.txt
for %%i in (6 6 8) do echo This is line %%i>>MyFile.txt
::
:: Build a Visual Basic Script
set skip=
set vbs_=%temp%\tmp$$$.vbs
findstr "'%skip%VBS" "%~f0" > %vbs_%
::
:: Run the script with Microsoft Windows Script Host Version 5.6
cscript //nologo %vbs_% < MyFile.txt
::
:: Clean up
for %%f in (%vbs_% MyFile.txt) do del %%f
endlocal & goto :EOF
'
'.............................................
'The Visual Basic Script
'
prev = "" 'VBS
first = true 'VBS
Do While Not WScript.StdIn.AtEndOfStream 'VBS
str = WScript.StdIn.ReadLine 'VBS
If (str <> prev) or first Then 'VBS
WScript.StdOut.WriteLine str 'VBS
End If 'VBS
prev = str 'VBS
first = false 'VBS
Loop 'VBS

The input file is
This is line 1
This is line 2
This is line 2
This is line 2

This is line 6
This is line 6
This is line 8

The output will be
This is line 1
This is line 2

This is line 6
This is line 8

Timo Salmi

unread,
May 4, 2005, 2:31:39 AM5/4/05
to
Timo Salmi wrote:
> The input file is
> This is line 1
> This is line 2
> This is line 2
> This is line 2
>
> This is line 6
> This is line 6
> This is line 8

Finally, if(!) you are prepared to accept omitting empty lines, then
@echo off & setlocal enableextensions enabledelayedexpansion


::
:: Make a test file
for %%i in (1 2 2 2) do echo This is line %%i>>MyFile.txt
echo.>>MyFile.txt
for %%i in (6 6 8) do echo This is line %%i>>MyFile.txt
::

set prev=
for /f "delims=" %%a in ('type Myfile.txt') do (
set str=%%a
if not [!str!]==[!prev!] echo %%a
set prev=!str!
)
::
:: Clean up
for %%f in (MyFile.txt) do del %%f
endlocal & goto :EOF
The output of the previous example would be
C:\_D\TEST>cmdfaq

Phil Robyn

unread,
May 4, 2005, 3:50:24 AM5/4/05
to
Timo Salmi wrote:

Hi, Timo:

Here's a modified version that displays empty lines:

- - - - - - - - - - begin screen capture - - - - - - - - - -
<Win2000> c:\cmd>type c:\temp\TheInputFile.txt


This is line 1
This is line 2
This is line 2
This is line 2

This is line 6
This is line 6
This is line 8

<Win2000> c:\cmd>demo\TimoDedupe


This is line 1
This is line 2

This is line 6
This is line 8

<Win2000> c:\cmd>rlist demo\TimoDedupe.cmd
=====begin c:\cmd\demo\TimoDedupe.cmd ====================
01. @echo off
02. setlocal
03. set prev=
04. for /f "tokens=1* delims=:" %%a in (
05. 'findstr /n /v /c:"Osama Bin Laden" c:\temp\TheInputFile.txt'
06. ) do call :main "%%b"
07. goto :EOF
08. :main
09. set str=%~1
10. if not defined str set "str= "
11. if "%str%" neq "%prev%" echo/%str%
12. set prev=%str%
13. goto :EOF
=====end c:\cmd\demo\TimoDedupe.cmd ====================
- - - - - - - - - - end screen capture - - - - - - - - - -

Also, in the WSH version you posted earlier, you probably don't need
the switch 'first', as upon first read of the file, 'str' will never
be equal to 'prev'.

--
Phil Robyn
Univ. of California, Berkeley

u n z i p m y a d d r e s s t o s e n d e - m a i l

Timo Salmi

unread,
May 4, 2005, 4:02:42 AM5/4/05
to
Phil Robyn wrote:
> Also, in the WSH version you posted earlier, you probably don't need
> the switch 'first', as upon first read of the file, 'str' will never
> be equal to 'prev'.

Actually, if the first line is empty.

ten.n...@virgin.net

unread,
May 4, 2005, 5:54:56 AM5/4/05
to
On Tue, 03 May 2005 19:34:35 -0500, Ted Davis wrote:

>
> for /f %%i in (nodup.txt) do (echo %%i | awk "{if(!($0 in
> A)){A[$0];print $0}})
>
> where awk is gawk.exe from
> <http://gnuwin32.sourceforge.net/packages/gawk.htm>. That is case
> sensitive, but there's an easy way to normalize all input to one case
> or the other. Anything that writes to STDOUT can go to the left of
> the pipe.

The output, is the result of parsing the information from 'Sysinternals'
Handle.exe. What I am wanting to do is create a portable solution, i.e
using handle and a batch file only, no 3rd party tools other than this
will be considered. I will probably be using the slimmed down output so
that I can stop each of the processes, using taskkill if possible on the
process name as opposed to the PID, I can then later restart the processes
if required with a simple 'start' command.

i.e.
for /f "tokens=1" %%A in ('handle.exe file.ext ^| findstr /v
BaseNamedObjects ^| findstr /v Handle ^| findstr /v Copyright ^| findstr
/v Sysinternals') do (
@echo %%A
)

Obviously the echo is temporary, in order to check output, I will probably
need a
call killit %%A
with
:killit
taskkill /f /im %1
etc.

I hope this helps explain my requirements further.

foxidrive

unread,
May 4, 2005, 7:46:17 AM5/4/05
to
On Wed, 04 May 2005 09:54:56 GMT, ten.n...@virgin.net wrote:

> The output, is the result of parsing the information from 'Sysinternals'
> Handle.exe. What I am wanting to do is create a portable solution, i.e
> using handle and a batch file only, no 3rd party tools other than this
> will be considered. I will probably be using the slimmed down output so
> that I can stop each of the processes, using taskkill if possible on the
> process name as opposed to the PID, I can then later restart the processes
> if required with a simple 'start' command.
>
> i.e.
> for /f "tokens=1" %%A in ('handle.exe file.ext ^| findstr /v
> BaseNamedObjects ^| findstr /v Handle ^| findstr /v Copyright ^| findstr
> /v Sysinternals') do (
> @echo %%A
> )
>
> Obviously the echo is temporary, in order to check output, I will probably
> need a
> call killit %%A
> with
>:killit
> taskkill /f /im %1
> etc.
>
> I hope this helps explain my requirements further.

This may help.

:: alphanumeric characters 'only'
:: the input file.txt is sorted before processing.
@echo off
sort <file.txt >file2.txt
set a=
set b=
type nul>fileout.txt
for /f "delims=" %%a in (file2.txt) do call :next "%%a"
del file2.txt
set a=
set b=
goto :EOF

:next
set a=%b%
set b=%~1
if not "%a%"=="%b%" echo %b%>>fileout.txt

Ted Davis

unread,
May 4, 2005, 8:54:30 AM5/4/05
to
On Wed, 04 May 2005 06:51:36 +0300, Timo Salmi <t...@uwasa.fi> wrote:

>Ted Davis wrote:
>> for /f %%i in (nodup.txt) do (echo %%i | awk "{if(!($0 in
>> A)){A[$0];print $0}})
>
>Unfortunately, also this solution is flawed. It has the same problems
>as Clay's solution (see my relevant reply).

-----


Unfortunately, the method has two flaws.

Only the first word of ech line is echoed. That is easy to remedy:
for /f "delims=" %%a in ('dir') do (

The second one is the very common, familiar one. The empty lines are
dropped."

-----

Well, the first word limit is
A) not due to the script, but to the input to the script that I
copied from another message, and
B) irrelavant because the sample data consists of single words per
line. I clearly stared that what precedes the pipe is irelavant to my
script.

>Plus it has a syntax
>error. The awk statement is missing the latter " needed.

Copy/paste error - the closing " got lost between the test file and
the message.

>
>If one takes the awk/sed route, the solution in Eric Pement's UNIX
>one-liners is
> sed '$!N; /^\(.*\)\n\1$/!P; D'
>It has to be adapted for PC syntax first.

I really can't support posting examples from another OS, even if you
specify that it won't work ... unless it's posted as part of an
exposition showing how a solution for the on-topic OS can be
developed.


--
T.E.D. (tda...@gearbox.maem.umr.edu)
SPAM filter: Messages to this address *must* contain "T.E.D."
somewhere in the body or they will be automatically rejected.

Timo Salmi

unread,
May 4, 2005, 9:26:26 AM5/4/05
to
Ted Davis wrote:
> On Wed, 04 May 2005 06:51:36 +0300, Timo Salmi <t...@uwasa.fi> wrote:
>>Ted Davis wrote:
>>> for /f %%i in (nodup.txt) do (echo %%i | awk "{if(!($0 in
>>>A)){A[$0];print $0}})

> B) irrelavant because the sample data consists of single words per


> line. I clearly stared that what precedes the pipe is irelavant to my
> script.

When possible, the more generic still is preferable. This not being
an actual consultation service for any single poster's exceptional
circumstances. But this was not a complaint. Just an observation.

>>Plus it has a syntax
>>error. The awk statement is missing the latter " needed.
> Copy/paste error - the closing " got lost between the test file and
> the message.

Strange, since it was not the last character that is missing. But
never mind. We all make mistakes, you and I included.

>> sed '$!N; /^\(.*\)\n\1$/!P; D'
>>It has to be adapted for PC syntax first.

> I really can't support posting examples from another OS, even if you

I was not looking for support but telling of one method for solving
the task posed. Besides, in program there is a lot of such cross
fertilization. And a direct quote is a direct quote.

> specify that it won't work ... unless it's posted as part of an
> exposition showing how a solution for the on-topic OS can be
> developed.

I did. Immediately after. Even if the conversion is extremely
trivial ' --> "

Ted Davis

unread,
May 4, 2005, 9:33:23 AM5/4/05
to
On Wed, 04 May 2005 09:54:56 GMT, ten.n...@virgin.net wrote:

>On Tue, 03 May 2005 19:34:35 -0500, Ted Davis wrote:
>
>>
>> for /f %%i in (nodup.txt) do (echo %%i | awk "{if(!($0 in
>> A)){A[$0];print $0}})
>>
>> where awk is gawk.exe from
>> <http://gnuwin32.sourceforge.net/packages/gawk.htm>. That is case
>> sensitive, but there's an easy way to normalize all input to one case
>> or the other. Anything that writes to STDOUT can go to the left of
>> the pipe.
>
>The output, is the result of parsing the information from 'Sysinternals'
>Handle.exe. What I am wanting to do is create a portable solution, i.e
>using handle and a batch file only, no 3rd party tools other than this
>will be considered.

Since that's critical information, you really should have made it
clear. Normally, when third-party tools are allowd, they are allowed,
so long as they are reputable and reliable.

Constraints delivered one at a time in response to solutions offered
that meet all the previous ones are *not* appreciated.

>I will probably be using the slimmed down output so
>that I can stop each of the processes, using taskkill if possible on the
>process name as opposed to the PID, I can then later restart the processes
>if required with a simple 'start' command.
>
>i.e.
>for /f "tokens=1" %%A in ('handle.exe file.ext ^| findstr /v
>BaseNamedObjects ^| findstr /v Handle ^| findstr /v Copyright ^| findstr
>/v Sysinternals') do (
> @echo %%A
>)
>

Please indent real lines two spaces per the convention here - wrapped
lines that can't easily be distinguished from new lines make for hard
to decipher code. Especially when it is needless complicated - I
think you want to isolate the parts to the report that are not header
or blank, i. e., just the data:
handle name | find ":"
does that.

>Obviously the echo is temporary, in order to check output, I will probably
>need a
> call killit %%A
>with
>:killit
>taskkill /f /im %1
>etc.
>
>I hope this helps explain my requirements further.

Not nearly far enough. I think I see a possible solution, but without
a definition for "portable", and a better description of what you are
trying to do, I'm not going to waste time devising something so
esoteric that only a very few here will understand it only to have it
shot down by yet another constraint you didn't tell us about ... not
when there is no clear reason other than you own mindset to reject the
one I have already presented.

billious

unread,
May 4, 2005, 11:12:25 AM5/4/05
to

"Timo Salmi" <t...@uwasa.fi> wrote in message
news:4278488b$1...@news.dnainternet.net...

> billious wrote:
>> for /f %%i in (nodup.txt) do echo %%i|find <nodup.rpt "%%i">nul &if
>> errorlevel 1 echo %%i>>nodup.rpt
>
> Same thing. Unfortunately the solution is flawed.
> "The system cannot find the file specified."
>
> Don't you good regulars test your solutions first. Not that this
> is a free service, and improving what we all post is one of the
> goals of the ng. Feedback about the intended solutions.
>
> All the best, Timo


Yes - I did test it, Timo.

Here's the paragraph that you excised (selects RED, 72-point <g>)

where nodup.txt is a simulation of your (lots of trivial stuff) and
nodup.rpt is an established 0-byte file (or echo/>nodup.rpt if you can
handle a leading-empty-line)

It doesn't generate "The system cannot find the file specified." IF you have
established nodup.rpt, preferably as an empty file or as a 1-line file using
echo/>nodup.rpt.

So - I tried

ECHO/>nodup.rpt&for /f %%i in (nodup.txt) do echo %%i|find <nodup.rpt

"%%i">nul &if errorlevel 1 echo %%i>>nodup.rpt

which worked, but generated a ugly error message "the process tried to write
to a nonexistent pipe" when I tried it, so I abandoned this approach. On
reading the resultant file, it appears that the report is correct
notwithstanding the screen message.

I've since run this one-liner hundreds of times. Normally, it's quiet.
Occasionally, it generated the "nonexistent pipe" message. Sometimes it even
gets enthusiatic enough to complain TWICE about the non-existent pipe.

On running

ECHO/>nodup.rpt


for /f %%i in (nodup.txt) do echo %%i|find <nodup.rpt "%%i">nul &if
errorlevel 1 echo %%i>>nodup.rpt

as a 2-line batch file, it seems quieter, but it still generates the
"nonexistent pipe" message about 10% of the time - which I find intriguing.
Annoying also, since it didn't show up in my original testing.

I've noted the flaw that using "echo/>..." adds an empty line to the report
file. Since the OP appeared to want a one-liner with no tempfiles and as it
turns out, no 3rd-party utilities either, I thought this was a reasonable -
and apparently-working solution. It keeps the original order of data lines
and doesn't rely on the duplicates' being grouped together. Following "FIND"
with a "/i" makes it case-insensitive too...

Now, had I been awake at 7am, I would have turned to chapter 41 of Timo's
Bible of DOS Techniques and changed this to

type nul>nodup.rpt&for /f %%i in (nodup.txt) do echo %%i|find <nodup.rpt

"%%i">nul &if errorlevel 1 echo %%i>>nodup.rpt

and poof! No more extra line in the output...though sadly an empty input
line won't appear on the report either.

Sadly, the occasional 'nonexistent pipe' persists, though :(

...Bill


ten.n...@virgin.net

unread,
May 4, 2005, 12:41:48 PM5/4/05
to
On Wed, 04 May 2005 21:46:17 +1000, foxidrive wrote:

>
> This may help.
>
> :: alphanumeric characters 'only'
> :: the input file.txt is sorted before processing.
> @echo off
> sort <file.txt >file2.txt
> set a=
> set b=
> type nul>fileout.txt
> for /f "delims=" %%a in (file2.txt) do call :next "%%a"
> del file2.txt
> set a=
> set b=
> goto :EOF
>
> :next
> set a=%b%
> set b=%~1
> if not "%a%"=="%b%" echo %b%>>fileout.txt

Thanks all for the ideas the following is a working solution
It uses code as provided by foxidrive!

----- the code -----
@echo off && setlocal


for /f "tokens=1" %%A in ('handle.exe file.ext ^| findstr /v BaseNamedObjects ^| findstr /v Handle ^| findstr /v Copyright ^| findstr /v Sysinternals') do (

@echo %%A>>file1.txt
)
sort <file1.txt >file2.txt


set a=
set b=
type nul>fileout.txt

for /f "delims=" %%B in (file2.txt) do call :nodupes "%%B"
del file?.txt
for /f "tokens=*" %%C in (fileout.txt) do call :killit %%C

<snip>...my unreleated stuff

for /f "tokens=*" %%G in (fileout.txt) do call :strtit %%G
del fileout.txt
endlocal && goto :eof

:nodupes


set a=%b%
set b=%~1
if not "%a%"=="%b%" echo %b%>>fileout.txt

goto :eof

:killit
start "" /w taskkill /f/im %1
goto :eof

<snip>...more other unreleated stuff

:strtit
start "" /w %1
--------------------
I would just like to add that I, in no way, intended to upset anyone!

My personal idea in using NT cmd was because it is built in to the systems upon which I work.
If something can be done using the built in tools, I will use it, within reason.
If there was no 'workable' solution for my requirements in this instance, I would have looked at other methods, including 3rd party tools and /or languages.
I do appreciate all responses, and have learned everything I know on batch scripting from this group over the last six months.
It is the first time I have felt the need to ask a question, and apologise to all for any 'newbieness'.
Once again thanks!

ten.n...@virgin.net

unread,
May 4, 2005, 5:50:21 PM5/4/05
to
On Wed, 04 May 2005 23:12:25 +0800, billious wrote:

> Yes - I did test it, Timo.

> <snip>


> Sadly, the occasional 'nonexistent pipe' persists, though :(

> <snip>
> ...Bill

Due to my error, (I had not changed one of the %%i to %%A), I've now managed to get the code from billious to work!
Although I do get sporadic but frequent single or double 'The process tried to write to a nonexistent pipe' messages.
It is shorter and appears to work very slightly faster than foxidrives!
I have yet to attempt the other(s) but will let you know in due course.

----- the code -----
@echo off && setlocal

type nul>fileout.txt


for /f "tokens=1" %%A in ('handle.exe file.ext ^| findstr /v BaseNamedObjects ^| findstr /v Handle ^| findstr /v Copyright ^| findstr /v Sysinternals') do (

echo %%A|find <fileout.txt "%%A">nul &if errorlevel 1 echo %%A>>fileout.txt
)
for /f "tokens=*" %%B in (fileout.txt) do call :killit %%B

<snip>...my unreleated stuff

for /f "tokens=*" %%F in (fileout.txt) do call :strtit %%F

Clay Calvert

unread,
May 4, 2005, 6:06:03 PM5/4/05
to
On Wed, 04 May 2005 06:24:55 +0300, Timo Salmi <t...@uwasa.fi> wrote:

>Unfortunately, the method has two flaws.
>
>Only the first word of ech line is echoed. That is easy to remedy:
> for /f "delims=" %%a in ('dir') do (

In his original example he had "tokens=1". I simply removed it
because it was redundant. Not a flaw.

>The second one is the very common, familiar one. The empty lines are
>dropped.

If the OP wanted only wanted non-redundant lines then what is the
importance of capturing blank lines? Also, not a flaw.

Timo Salmi

unread,
May 4, 2005, 6:35:33 PM5/4/05
to
Clay Calvert wrote:
> On Wed, 04 May 2005 06:24:55 +0300, Timo Salmi <t...@uwasa.fi> wrote:
>>Unfortunately, the method has two flaws.
> importance of capturing blank lines? Also, not a flaw.

Ok, a feature then. Narrowly customized for the OP's specific,
non-generic needs. Using the directory listing as the example data
managed to fool me.

ten.n...@virgin.net

unread,
May 4, 2005, 7:09:16 PM5/4/05
to
On Tue, 03 May 2005 20:55:14 -0400, Clay Calvert wrote:

> Since we don't know what the trivial stuff is, I used the output of
> DIR sorted by date for this example.
>
> @echo off
> setlocal enabledelayedexpansion
> (set line=)
> for /f %%a in ('dir /od') do (
> if %%a' NEQ !line!' echo %%a & set Line=%%a)

Your method works fine for me, since as you say, I only required the first
token, therefore negating 'delims' and blank lines in the output would
have also been a problem.

I now have four slightly different working solutions, listed in order of
speed, because a little competition never hurts!
Clay Calvert 'OP tailored version'
Timo Salmi 'Phil Robyn version'
billious 'pipe message version'
foxidrive 'multifile version'

Once again thanks all!

Timo Salmi

unread,
May 4, 2005, 7:14:29 PM5/4/05
to
ten.n...@virgin.net wrote:
> I now have four slightly different working solutions, listed in order of
> speed, because a little competition never hurts!

Excellent. The best of two worlds. You have a specific solution that
best fits your need. And several solutions surfaced on the side which
function also for the more generic "uniq" situation.

Timo Salmi

unread,
May 5, 2005, 11:51:10 AM5/5/05
to
Phil Robyn wrote:

> Timo Salmi wrote:
>> Finally, if(!) you are prepared to accept omitting empty lines, then
>> @echo off & setlocal enableextensions enabledelayedexpansion

> Hi, Timo:


> Here's a modified version that displays empty lines:

> <Win2000> c:\cmd>rlist demo\TimoDedupe.cmd


> =====begin c:\cmd\demo\TimoDedupe.cmd ====================

Nice. Thank you Phil. I'll include a Google link to your posting into
my FAQ.

I took another crack at the problem, and came up (not surprisingly)
with a very similar solution.

DRAFT

Can this task be solved with a pure cmd script so that the empty
lines are not omitted? Yes, but the solution is a bit kludgy and
complicated. And the issue of poison characters remains.


@echo off & setlocal enableextensions enabledelayedexpansion
::
:: Make a test file

echo.>>MyFile.txt
for %%i in (2 3 3 3) do echo This is line %%i>>MyFile.txt
echo.>>MyFile.txt
for %%i in (7 7 9 10 11) do echo This is line "%%i">>MyFile.txt
::
:: Process
for %%v in (prev LineCount) do set %%v=


for /f "delims=" %%a in (

'findstr /n /v /c:"SomeUnlikelyString" Myfile.txt') do (
set str=%%a
set /a LineCount+=1
set /a mod = LineCount/10 + 2
call :WriteOneLine "!str!" "!prev!" !mod!


set prev=!str!
)
::
:: Clean up
for %%f in (MyFile.txt) do del %%f
endlocal & goto :EOF

::
:: =============================================
:WriteOneLine
setlocal
set str=%~1
set prev=%~2
set offset=%3
set str=!str:~%offset%!
set prev=!prev:~%offset%!
if not [!str!]==[!prev!] echo.!str!
endlocal & goto :EOF

The test input file will be
---

This is line 2
This is line 3
This is line 3
This is line 3

This is line "7"
This is line "7"
This is line "9"
This is line "10"
This is line "11"
---

The test output will be
---
C:\_D\TEST>cmdfaq

This is line 2
This is line 3

This is line "7"
This is line "9"
This is line "10"
This is line "11"
---

billious

unread,
May 6, 2005, 12:20:42 AM5/6/05
to

"Timo Salmi" <t...@uwasa.fi> wrote in message
news:427a40f8$0$28531$9b53...@news.fv.fi...

> Phil Robyn wrote:
>> Timo Salmi wrote:
[PR solution snipped]

> DRAFT
>
> Can this task be solved with a pure cmd script so that the empty
> lines are not omitted? Yes, but the solution is a bit kludgy and
> complicated. And the issue of poison characters remains.
[TM solution & commentary snipped]

Here's a solution that seems immune from Timo's poison characters - except
rabbit's ears (22h) or quotes (27h)
It has a limit of 127 characters per line, imposed by FINDSTR. It returns
errorlevel 0 or 1 if it isn't given or can't find the data file. Rabbit's
ears or quotes, like brussels sprouts, should not be served up, as it will
make the batch sick.


[01]@echo off
[02]set ysf=%1
[03]if not defined ysf goto syntax
[04]if not exist %ysf% goto nofile
[05]set ybl=0
[06]set yln=0
[07]for /f "tokens=1* skip=2 delims=]" %%i in ('find /n /v "" %ysf%') do set
ylf=%%j&call :blank&&if not errorlevel 1 for /f "tokens=1 delims=:" %%k in
('findstr /b /e /n /c:"%%j" %1') do call :dupchk %%k&if errorlevel 1 echo
%%j
[08]echo n|find "n">nul
[09]:exit
[10]for %%i in (ysf ybl yln ylf yfl) do set %%i=
[11]goto :eof
[12]
[13]:syntax
[14]echo syntax is %0 filename
[15]goto error
[16]
[17]:nofile
[18]echo %1 not found - sorry!
[19]:error
[20]echo y|find "n">nul
[21]goto exit
[22]
[23]:dupchk
[24]if %yfl%==d set yfl=S
[25]if %yfl%%1==s%yln% set yfl=d
[26]if %yfl%==s set yfl=S
[27]echo %yfl%|find /i "s" >nul
[28]goto :eof
[29]
[30]:blank
[31]set yfl=s
[32]set/a yln+=1
[33]if %ybl%==1 set ybl=2
[34]echo n|find "n">nul
[35]if defined ylf goto :eof
[36]set /a ybl+=1
[37]echo y|find "n">nul
[38]if %ybl%==1 echo/
[39]set ybl=1
[40]goto :eof


Each line begins [number]. Lines will be wrapped in transmission and need to
be rejoined. The [number] at the beginning of each line needs to be removed.

It doesn't generate "nonexistent pipe" errors either. I'm glad of that.
Don't want data leaking out of my system.....

...Bill


Timo Salmi

unread,
May 6, 2005, 5:29:32 PM5/6/05
to
To put things in perspective. By quite a coincidence I just needed to
perform that task myself combining two lists of newsgroups and then
removing the duplicates. I didn't have to think for one second which
route to take when the situation came up for real. Skipped all our
nice and fancy scripts and used the UNIX port uniq.exe without any
hesitation. Interesting.

ten.n...@virgin.net

unread,
May 10, 2005, 4:50:47 PM5/10/05
to
On Wed, 04 May 2005 23:09:16 +0000, ten.nigriv wrote:

> I now have four slightly different working solutions, listed in order of
> speed, because a little competition never hurts!
> Clay Calvert 'OP tailored version'
> Timo Salmi 'Phil Robyn version'
> billious 'pipe message version'
> foxidrive 'multifile version'
>
> Once again thanks all!

I spoke a little too soon, I have a new problem now, just wasn't sure if
to add it here or start a new topic!

My problem is that there are occasions when a file reported by handle as
the 'locker' is a service rather than a normal process. Obviously this
means that the taskkill command alone is inadequate.

So I tried this, not only is it probably not very accurate, I am having an
access denied error on at least one of the keys, will get errors due to
character limitations using findstr as opposed to find, but the main
problem is that the taskkill bit doesn't seem to work.

Have I coded wrongly? are the commands just tosh? is there another way to
distinguish between a service and a normal task?

If I have to resort to 3rd party addons, so be it, I already am so what
the hell!

TIA
----- code -----
:killit
for /f "tokens=*" %%i in ('reg query "HKLM\SYSTEM\CurrentControlSet\Services" /S ^| find /i "%~1"') DO (
if errorlevel 0 (
@echo sc stop %1
) else (
@echo taskkill /f /im %1
)
)
sleep 5
goto :eof
----- end -----

Phil Robyn

unread,
May 10, 2005, 5:03:53 PM5/10/05
to

C:\cmd>net help stop
The syntax of this command is:


NET STOP
service

NET STOP stops Windows services.

Stopping a service cancels any network connections the service is
using. Also, some services are dependent on others. Stopping one
service can stop others.

Some services cannot be stopped.

service May be one of the following services:
ALERTER
BROWSER
CLIENT SERVICE FOR NETWARE
CLIPBOOK
DHCP CLIENT
FILE REPLICATION
MESSENGER
NET LOGON
NT LM SECURITY SUPPORT PROVIDER
REMOTE ACCESS CONNECTION MANAGER
ROUTING AND REMOTE ACCESS
RPCLOCATOR
SCHEDULE
SERVER
SPOOLER
TCP/IP NETBIOS HELPER SERVICE
UPS
WORKSTATION

NET STOP can also stop services not provided with Windows.

NET HELP command | MORE displays Help one screen at a time.

ten.n...@virgin.net

unread,
May 10, 2005, 5:11:05 PM5/10/05
to
On Tue, 10 May 2005 14:03:53 -0700, Phil Robyn wrote:

> NET STOP
> service
>
> NET STOP stops Windows services.
>

My problem is that handle is only giving me an executable name, I cannot
use that directly in NET command, which requires a 'service name'

Phil Robyn

unread,
May 10, 2005, 5:14:27 PM5/10/05
to

C:\cmd>net start
These Windows services are started:

Application Layer Gateway Service
Automatic Updates
Background Intelligent Transfer Service
COM+ Event System
Computer Browser
Cryptographic Services
DCOM Server Process Launcher
DHCP Client
Distributed Link Tracking Client
DNS Client
Error Reporting Service
Event Log
Help and Support
IPSEC Services
Logical Disk Manager
Net Logon
Network Connections
Network Location Awareness (NLA)
Plug and Play
Print Spooler
Protected Storage
Remote Procedure Call (RPC)
Remote Registry
SavRoam
Secondary Logon
Security Accounts Manager
Server
Shell Hardware Detection
SSDP Discovery Service
Symantec AntiVirus
Symantec AntiVirus Definition Watcher
Symantec Event Manager
Symantec Network Drivers Service
Symantec Network Proxy
Symantec SecurePort
Symantec Settings Manager
System Event Notification
Task Scheduler
TCP/IP NetBIOS Helper
Terminal Services
Themes
WebClient
Windows Audio
Windows Firewall/Internet Connection Sharing (ICS)
Windows Management Instrumentation
Windows Time
Wireless Zero Configuration
Workstation

. . . . . . . . . . . . . . . . . . . .
So which service is it that you want to stop? Won't the service
name always be the same?

Clay Calvert

unread,
May 10, 2005, 6:47:06 PM5/10/05
to
On Tue, 10 May 2005 14:14:27 -0700, Phil Robyn <pro...@berkeley.edu>
wrote:
<snip>

>
>. . . . . . . . . . . . . . . . . . . .
>So which service is it that you want to stop? Won't the service
>name always be the same?

The process name of a service does not always match the service name.
For example, the Server service is launched under SVChost.exe, which
is shown in the first example below.

Also, as I understand it, SC requires the true Service Name, whereas
Net Start _shows_ the Display Name.

Here's an abbreviated output of the Server service as listed in the
registry. The 'name' is LanManServer, but the DisplayName is Server.

HKLM\system\currentcontrolset\services\lanmanserver
Type REG_DWORD 0x20
Start REG_DWORD 0x2
ImagePath REG_EXPAND_SZ %SystemRoot%\System32\svchost.exe -k
netsvcs
DisplayName REG_SZ Server

As already shown, running Net Start will display "Server" for the
server service. Below is using SC from the command prompt.

C:\>sc query server
[SC] EnumQueryServicesStatus:OpenService FAILED 1060:

The specified service does not exist as an installed service.

C:\>sc query lanmanserver

SERVICE_NAME: lanmanserver
TYPE : 20 WIN32_SHARE_PROCESS
STATE : 4 RUNNING
(STOPPABLE,PAUSABLE,ACCEPTS_SHUTDOWN)
WIN32_EXIT_CODE : 0 (0x0)
SERVICE_EXIT_CODE : 0 (0x0)
CHECKPOINT : 0x0
WAIT_HINT : 0x0


All that being said, the Net Stop/Start command will still work with
the 'proper' name as well as the Display Name.


C:\>net stop server
The following services are dependent on the Server service.
Stopping the Server service will also stop these services.

Computer Browser

Do you want to continue this operation? (Y/N) [N]: n


C:\>net stop lanmanserver
The following services are dependent on the Server service.
Stopping the Server service will also stop these services.

Computer Browser

Do you want to continue this operation? (Y/N) [N]: n

I've got to run now, but for Ten, or whatever your name is,
arbitrarily stopping services is not a good idea.

Phil Robyn

unread,
May 10, 2005, 7:19:37 PM5/10/05
to
Clay Calvert wrote:

Hi, Clay, nice post! Ten, does this help?

- - - - - - - - - - begin screen capture WinXP - - - - - - - - - -

==========begin file c:\cmd\demo\GetServiceDisplayName.cmd ==========
001. @echo off
002. setlocal
003. sc query type= service > %temp%\service.info
004. for /f "tokens=1 delims=:" %%a in (
005. 'findstr /n /c:"%~1" %temp%\service.info'
006. ) do set /a process_line = %%a
007. more /e +%process_line% %temp%\service.info > %temp%\service.wrk1
008. set /p first_line=<%temp%\service.wrk1
009. for /f "tokens=1* delims=: " %%a in (
010. "%first_line%"
011. ) do set display_name=%%b
012. echo/
013. echo/Service display name is %display_name%
014. echo/Service process name is %1
==========end file c:\cmd\demo\GetServiceDisplayName.cmd ==========


==========begin file c:\cmd\demo\GetServiceProcessName.cmd ==========
001. @echo off
002. setlocal
003. sc query type= service > %temp%\service.info
004. for /f "tokens=1 delims=:" %%a in (
005. 'findstr /n /c:"%~1" %temp%\service.info'
006. ) do set /a process_line = %%a - 2
007. more /e +%process_line% %temp%\service.info > %temp%\service.wrk1
008. set /p first_line=<%temp%\service.wrk1
009. for /f "tokens=2 delims=: " %%a in (
010. "%first_line%"
011. ) do set process_name=%%a
012. echo/
013. echo/Service display name is %1
014. echo/Service process name is %process_name%
==========end file c:\cmd\demo\GetServiceProcessName.cmd ==========

C:\cmd>demo\GetServiceProcessName "Symantec Settings Manager"

Service display name is "Symantec Settings Manager"
Service process name is ccSetMgr

C:\cmd>demo\GetServiceDisplayName "ERSvc"

Service display name is Error Reporting Service
Service process name is "ERSvc"
- - - - - - - - - - end screen capture WinXP - - - - - - - - - -

ten.n...@virgin.net

unread,
May 10, 2005, 7:50:46 PM5/10/05
to
On Tue, 10 May 2005 16:19:37 -0700, Phil Robyn wrote:

>
> Hi, Clay, nice post! Ten, does this help?
>
> - - - - - - - - - - begin screen capture WinXP - - - - - - - - - -

> <snip>


> - - - - - - - - - - end screen capture WinXP - - - - - - - - - -

I'll take a good look at it tomorrow, in the mean time, just to let you
know that the SC bit is actually working okay so far, regardless of the
error messages, (they obviously dont output an errorlevel!), It's the
taskkill bit isn't processed for items not found in the services section
of the registry.

The services are generally not 'Standard' Windows services, rather from
add on software, usually security type scanners firewalls and monitors.

Would I be better off for now simply changing the 'else' to 'if errorlevel
neq 0', for instance.

I think my problem stems from needing a sure fire method of identifying
'service' or 'task' given only the executable name.

0 new messages