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

Trouble with Break

0 views
Skip to first unread message

RickB

unread,
Jul 18, 2008, 3:27:44 PM7/18/08
to
I want a function that quits searching for a file after the file is
found.

From the command prompt this works fine.

ls c:\windows -i 'notepad.exe' -r | % {$_; break}

But a rather large variety of attempts to somehow save the returned
value all fail.

Kirk Munro [MVP]

unread,
Jul 18, 2008, 5:07:06 PM7/18/08
to
Hi Rick,

You can't accomplish what you want by using break a pipeline like that.
It's actually breaking your entire command. If you run this interactively,
it simply terminates your current command. If you do it in a script or
function, it terminates your script or function.

i.e. There is no way to use PowerShell to tell an earlier stage in a
pipeline to stop processing that pipeline at the moment.

Try this instead:

ls C:\windows -i 'notepad.exe' -r | select -first 1

This only returns the first item that comes out of the first stage of the
pipeline, however the search will actually continue. The select
(Select-Object) command just throws away the remaining items that come in
from the pipeline. I believe that's the best you'll be able to do for now.

--
Kirk Munro [MVP]
Poshoholic
http://poshoholic.com

"RickB" <rbie...@i1.net> a écrit dans le message de groupe de discussion :
09f1328b-a0a4-4a16...@s50g2000hsb.googlegroups.com...

tojo2000

unread,
Jul 18, 2008, 6:12:18 PM7/18/08
to
On Jul 18, 2:07 pm, "Kirk Munro [MVP]"

<see.my.about.page...@my.poshoholic.com.blog> wrote:
> Hi Rick,
>
> You can't accomplish what you want by using break a pipeline like that.
> It's actually breaking your entire command.  If you run this interactively,
> it simply terminates your current command.  If you do it in a script or
> function, it terminates your script or function.
>
> i.e. There is no way to use PowerShell to tell an earlier stage in a
> pipeline to stop processing that pipeline at the moment.
>
> Try this instead:
>
> ls C:\windows -i 'notepad.exe' -r | select -first 1
>
> This only returns the first item that comes out of the first stage of the
> pipeline, however the search will actually continue.  The select
> (Select-Object) command just throws away the remaining items that come in
> from the pipeline.  I believe that's the best you'll be able to do for now.
>
> --
> Kirk Munro [MVP]
> Poshoholichttp://poshoholic.com
>
> "RickB" <rbiel...@i1.net> a écrit dans le message de groupe de discussion :
> 09f1328b-a0a4-4a16-a8ca-4a9b9e92e...@s50g2000hsb.googlegroups.com...

>
> > I want a function that quits searching for a file after the file is
> > found.
>
> > From the command prompt this works fine.
>
> > ls c:\windows -i 'notepad.exe' -r | % {$_; break}
>
> > But a rather large variety of attempts to somehow save the returned
> > value all fail.

I have a function that will do what you want. It will do a dir on the
root directory and

# Find-File $path $filename
# Finds the first instance of a file under a directory
#
# Args:
# $path: the path to start looking under
# $filename: the argument to pass to dir. Use * as a wildcard.
#
# Returns:
# The first matching file or nothing
function Find-File ([string]$path, [string]$filename) {
$files = @(dir $path)

foreach ($file in $files) {
if (-not ($file.Mode -match '^d') -and ($file.Name -like
"$filename")) {
return $file
}
}

foreach ($file in $files) {
if ($file.Mode -match '^d') {
$result = (Get-File $file.FullName $filename)

if ($result) {
return $result
}
}
}
}

tojo2000

unread,
Jul 18, 2008, 6:43:25 PM7/18/08
to

I accidentally hit send too soon. Basically it does a non-recursive
dir on each directory and then recurses itself into each subdirectory
so that it has the ability to stop early if it finds a matching file.
One weakness is that you can't use this to find a directory because it
will just recurse through the directory.

RickB

unread,
Jul 21, 2008, 3:15:05 PM7/21/08
to

I was sure enough that I remembered this problem being
solved that I continued searching. Although I never found
the original problem or solution description I did finally
remember that it involved THROW which lead me to this.

function first-match ([string]$template){
(&{trap {$file;continue}
ls c:\windows -i $template -r | % {$file = $_;throw}})}

Initial testing suggests it might be a general workaround
for this type of problem.


On Jul 18, 4:07 pm, "Kirk Munro [MVP]"


<see.my.about.page...@my.poshoholic.com.blog> wrote:
> Hi Rick,
>
> You can't accomplish what you want by using break a pipeline like that.
> It's actually breaking your entire command.  If you run this interactively,
> it simply terminates your current command.  If you do it in a script or
> function, it terminates your script or function.
>
> i.e. There is no way to use PowerShell to tell an earlier stage in a
> pipeline to stop processing that pipeline at the moment.
>
> Try this instead:
>
> ls C:\windows -i 'notepad.exe' -r | select -first 1
>
> This only returns the first item that comes out of the first stage of the
> pipeline, however the search will actually continue.  The select
> (Select-Object) command just throws away the remaining items that come in
> from the pipeline.  I believe that's the best you'll be able to do for now.
>
> --
> Kirk Munro [MVP]
> Poshoholichttp://poshoholic.com
>

> "RickB" <rbiel...@i1.net> a écrit dans le message de groupe de discussion :
> 09f1328b-a0a4-4a16-a8ca-4a9b9e92e...@s50g2000hsb.googlegroups.com...


>
>
>
> > I want a function that quits searching for a file after the file is
> > found.
>
> > From the command prompt this works fine.
>
> > ls c:\windows -i 'notepad.exe' -r | % {$_; break}
>
> > But a rather large variety of attempts to somehow save the returned

> > value all fail.- Hide quoted text -
>
> - Show quoted text -

tojo2000

unread,
Jul 21, 2008, 4:23:05 PM7/21/08
to

Just to be clear, this fixes the issue with break killing the command,
but the 'ls -r' will still complete its operation before piping the
results to that part of the command, right?

RickB

unread,
Jul 21, 2008, 5:00:45 PM7/21/08
to
> results to that part of the command, right?- Hide quoted text -

>
> - Show quoted text -

No. The amount of time that the command takes
to execute indicates that searching for additional
files matching the template stops immediately.

Wrapping the pipeline in a trap{continue} appears to be a
generalized method of circumventing the problem of not being
able to cancel the pipeline.

PS 79> function first-match ([string]$template){
>> (&{trap {continue}
>> ls c:\ -i $template -r |%{$file = $_;$file;if ($file.name -gt 'ar'){throw}}|%{"File $($_.name) found"}})}
>>
PS 80> get-date;first-match 'a*';get-date

Monday, July 21, 2008 3:56:10 PM
File Application Data found
File ActionEditor.bmp found
File ActionEditor.config found
File ActionEditor.exe found
File ActionEditorW.exe found
File AccessControlTable.xml found
File accessInteraction.gif found
File accessSQL.gif found
File appserver.gif found
File appserver_win.gif found
File arrow.gif found
Monday, July 21, 2008 3:56:10 PM

PS 81>

I see no delay after "File arrow.gif found" and the time being printed
or the PS 81> prompt appearing afterwards.
This seems to work as a general rule.

tojo2000

unread,
Jul 21, 2008, 5:22:46 PM7/21/08
to

Yes, but the question is not whether the execution is interrupted and
continued within that section of the pipe, but whether the initial ls -
r will finish searching all subdirectories even after a result has
been found, unless I misunderstand the OP's question. By the time
your output is printed the ls -r is already done, and the second and
third sections are executed only on the results of the ls -r, right?

tojo2000

unread,
Jul 21, 2008, 5:30:49 PM7/21/08
to

Nevermind, I see it now.

Shay Levy [MVP]

unread,
Jul 21, 2008, 5:33:39 PM7/21/08
to
Hi RickB,

Try the foreach statement instead:

foreach($file in (dir $env:WINDIR)){
if($file.name -eq 'notepad.exe') {$file; break}
}


---
Shay Levy
Windows PowerShell MVP
blog: http://blogs.microsoft.co.il/blogs/ScriptFanatic

R> I want a function that quits searching for a file after the file is
R> found.
R>
R> From the command prompt this works fine.
R>
R> ls c:\windows -i 'notepad.exe' -r | % {$_; break}
R>
R> But a rather large variety of attempts to somehow save the returned
R> value all fail.
R>


tojo2000

unread,
Jul 21, 2008, 6:47:24 PM7/21/08
to

By wrapping the dir statement in parentheses, though, you're causing
the dir statement to be evaluated before continuing (I made sure to
test it this time), so this won't allow the function to break out of
the loop when it finds the file until after it's recursively searched
the entire directory, so that doesn't do exactly what he wanted.

Here's another function that will do the same as the trap function but
is a bit more generic, expanding on the trap/throw solution:

function First-File([string]$path, [string]$fileglob){
Get-ChildItem $path -include $fileglob -r | foreach {Write-Output
$_; continue}
}


RickB

unread,
Jul 22, 2008, 8:49:08 AM7/22/08
to

I only posted an example that I thought would work on all systems.
My original problem was that I needed to search the entire system
for a particular file but once I found it I didn't want to continue
the
search because it takes so long and serves no purpose.

Shay Levy [MVP]

unread,
Jul 22, 2008, 11:05:17 AM7/22/08
to
Hi RickB,

Yes, I know :) trying to figure out a solution myself. Keep trying...


---
Shay Levy
Windows PowerShell MVP
blog: http://blogs.microsoft.co.il/blogs/ScriptFanatic

R> On Jul 21, 4:33 pm, Shay Levy [MVP] <n...@addre.ss> wrote:
R>

>> Hi RickB,
>>
>> Try the foreach statement instead:
>>
>> foreach($file in (dir $env:WINDIR)){
>> if($file.name -eq 'notepad.exe') {$file; break}
>> }
>>
>> ---
>> Shay Levy
>> Windows PowerShell MVP
>> blog:http://blogs.microsoft.co.il/blogs/ScriptFanatic
>> R> I want a function that quits searching for a file after the file
>> is
>> R> found.
>> R>
>> R> From the command prompt this works fine.
>> R>
>> R> ls c:\windows -i 'notepad.exe' -r | % {$_; break}
>> R>
>> R> But a rather large variety of attempts to somehow save the
>> returned
>> R> value all fail.
>> R>
R> I only posted an example that I thought would work on all systems.

R> My original problem was that I needed to search the entire system
R> for a particular file but once I found it I didn't want to continue
R> the
R> search because it takes so long and serves no purpose.


0 new messages