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

break pipeline and return value

147 views
Skip to first unread message

Vadims Podans

unread,
Mar 6, 2009, 3:51:32 AM3/6/09
to
Hi!
Is there any way to break pipeline at specified moment, return value from
function to calling variable and pass value to next pipeline?
for example:
function First2 {
Begin {
$n = 2
$a = @()
}
Process {
if ($n -eq 0) {break}
else {
$a += $_
--$n
if ($n -eq 0) {return $a}
}
}
}
and usage:
1..5 | first2
will return only two first objects from pipeline and breaks pipeline.
However, if I try to save these two object to variable:
$b = 1..5 | first2
$b variable is empty.

I know only only one method to exit from Process phase or break pipeline -
Break command, but this command doesn't return anything to calling variable,
only to next pipeline:
1..5 | first2 | %{$_}

Any help is appreciated.
--
WBR, Vadims Podans
PowerShell blog - www.sysadmins.lv

Camelot.vcf

Josh Einstein

unread,
Mar 6, 2009, 4:48:45 AM3/6/09
to
I've been trying to find ways to do that too but to no avail. The only thing
you can do is let the pipeline run to completion but just stop returning
values. See the following function for an example of what I mean. Once the
first value is returned, it sets a variable so that it can skip evaluating
the predicate on subsequent iterations.

1..10 | Linq-First { $_ -gt 5 } # returns 6

##############################################################################
#.Synopsis
# Returns the first element in a sequence that satisfies a specified
condition.
#
#.Parameter Predicate
# A function to test each element for a condition.
#
#.Example
# 1..10 | Linq-First { $_ -gt 5 }
#
#.ReturnValue
# The first element in the sequence that passes the test in the specified
# predicate or nothing if no elements pass the test.
##############################################################################
filter Linq-First([ScriptBlock]$Predicate) {

if ( $_ -eq $null ) { return }
if ( $Local:Result ) { return }

if ( &$Predicate ) {
$Local:Result=$true
$_
}

}

"Vadims Podans" <vpodans> wrote in message
news:D62FBE0D-9F80-47A5...@microsoft.com...

Vadims Podans

unread,
Mar 6, 2009, 5:16:22 AM3/6/09
to
I want to get N first objects. And here might be any type objects. Like
Select -first N, but Select doesn't break pipeline. something like this:

{some data collection} | first 5 - should return only first 5 objects (my
function does this)
$a = {some data collection} | first 5 - should write these first 5 objects
to $a variable. And here I have some troubles with my function. These
objects are streamed to next pipeline, but not to variable.


--
WBR, Vadims Podans
PowerShell blog - www.sysadmins.lv

"Josh Einstein" <joshei...@hotmail.com> rakstīja ziņojumā
"news:F0677FF1-BF19-4A06...@microsoft.com"...

Shay Levy [MVP]

unread,
Mar 6, 2009, 9:17:35 AM3/6/09
to
Hi Vadims,


I've filed a *bug* on connect last year regarding that behaviour, you may
want to vote on it:
https://connect.microsoft.com/feedback/ViewFeedback.aspx?FeedbackID=332685&SiteID=99

# stream output to a variable or down the pipe.
function Select-First {
param([int]$num=2)

Begin {
[int]$i=0
}

Process {
if ($i -lt $num) {$i++; $_}
}
}

# save results to a variable (deafult value of first 2)
PS > $a=1..10 | Select-First
PS > $a
1
2


PS 7> 1..5 | Select-First -n 3 | foreach {$_}
1
2
3


---
Shay Levy
Windows PowerShell MVP
http://blogs.microsoft.co.il/blogs/ScriptFanatic
PowerShell Toolbar: http://tinyurl.com/PSToolbar

Vv> I want to get N first objects. And here might be any type objects.
Vv> Like Select -first N, but Select doesn't break pipeline. something
Vv> like this:
Vv>
Vv> {some data collection} | first 5 - should return only first 5
Vv> objects (my
Vv> function does this)
Vv> $a = {some data collection} | first 5 - should write these first 5
Vv> objects
Vv> to $a variable. And here I have some troubles with my function.
Vv> These
Vv> objects are streamed to next pipeline, but not to variable.
Vv> "Josh Einstein" <joshei...@hotmail.com> rakst?ja zi?ojum?
Vv> "news:F0677FF1-BF19-4A06...@microsoft.com"...
Vv>

RickB

unread,
Mar 6, 2009, 10:14:07 AM3/6/09
to
>  Camelot.vcf
> < 1KViewDownload

Assuming your example is generic there are several things you could
mean.
PS 20> $a = 1..5|Select-Object -first 3
PS 21> $a
1
2
3

This behavior can be duplicated like this
PS 23> function FirstN ([int]$count = 2) {
>> process {if ($count-- -gt 0){$_}}}
>>
PS 24> 1..6|firstn
1
2
PS 25> $a = 1..6|firstn
PS 26> $a
1
2

If you truly want to stop the pipeline at some point (AFAIK) the only
way is to throw.
The problem with throwing is that you then need to catch/trap the
throw or your routine fails.
If that weren't bad enough, the item you throw on will be lost unless
your catch knows how to retrieve it.

As an example, I wanted to find a very specific file that might be
anywhere on the drive.

DIR C:\* -I $name -R

This would usually find the file pretty quickly but then it would
continue searching the entire drive for more copies (which took a long
time) even though no more copies existed and I really didn't care if
they did.

&{trap {$_.TargetObject;continue} DIR C:\* -I $name -R|%{throw $_}}

This simply throws the item I'm looking for and I catch it and go on.
If I wanted to only emit the first 10 files matching a pattern I have
combinations of these choices.
I could wait for the 11th item to be found before throwing, thus
emitting normally and/or processing the first 10 before the throw that
kills the pipeline.
I could accumulate all the desired items and throw them so I could
process them after catching or trapping the error.
Or I could nest pipelines where the inner one is stopped at the
appropriate time so it stops emitting to the outer pipeline which can
then execute normally.

Kiron

unread,
Mar 6, 2009, 10:34:10 AM3/6/09
to
A while back I wrote this filters to stop the pipeline and set the object, or an array of objects to a variable in the caller's scope:

filter FirstObj ([string]$vName = '') {
if ($vName) {sv $vName $_ -s 1} else {$_}
break
}

filter FirstElements ([int]$max = 2, [string]$vName = '') {
if ($max -le 0) {break} else {$_arr += ,$_}
if (!--$max) {
if ($vName) {sv $vName $_arr -s 1} else {$_arr}
break
}
}

They work well in the console but not in a script, they break out of the script. So I modified them, but to call them inside a script you need to wrap the pipeline in an infinite named loop, pass the loop's label to it so it doesn't break the script:

filter FirstObj ([string]$vName = '', $label) {
if ($vName) {sv $vName $_ -s 1} else {$_}
if ($label) {break $label} else {break}
}

filter FirstElements ([int]$max = 2, [string]$vName = '', $label) {
if ($max -le 0) {break} else {$_arr += ,$_}
if (!--$max) {
if ($vName) {sv $vName $_arr -s 1} else {$_arr}
if ($label) {break $label} else {break}
}
}

# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - #
# in the console, no label necessary
1..1gb | ? {!($_ % 13)} | FirstObj v13
1..1gb | ? {!($_ % 17)} | FirstElements 3 arr13
$v13
$arr13.length
"$arr13"

# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - #
# sample scripts
# -< script1.ps1 >-
'hi'
:x while (1) {1..1gb | ? {!($_ % 7)} | FirstObj v1 x}
$v1
$v1 * 3
'bye'
# -< script1.ps1 >-
# -< script2.ps1 >-
'hi'
:y while (1) {1..1gb | ? {!($_ % 12)} | FirstElements 3 v2 y}
foreach ($e in $v2) {
$e
$e * 2
}
'bye'

# -< script2.ps1 >-
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - #
.\script1.ps1
.\script2.ps1

--
Kiron

Vadims Podans

unread,
Mar 6, 2009, 10:43:30 AM3/6/09
to
Hy, Shay!
I vote on connect. I see that your script only returns first two objects,
but doesn't break a pipeline:
[vPodans] (measure-command {gwmi win32_ntlogevent -filter "logfile='system'"
| select-first 1}).totalseconds
44,5870382
[vPodans] (measure-command {gwmi win32_ntlogevent -filter "logfile='system'"
| select -first 1}).totalseconds
45,6124848

I will try to find a workaround which helps to acheive all goals. In any
case - thank you for help!


--
WBR, Vadims Podans
PowerShell blog - www.sysadmins.lv

"Shay Levy [MVP]" <n...@addre.ss> rakstīja ziņojumā
"news:95d80893704f78...@news.microsoft.com"...

Vadims Podans

unread,
Mar 6, 2009, 10:55:16 AM3/6/09
to
Hi, Kiron. Yesterday I read your suggestion (found somewhere in google).
Yes, your filters works fine, but I hope that here is a way to avoid this
variable in the end. Looks like, I want something strange :)
Thanks in any way!

--
WBR, Vadims Podans
PowerShell blog - www.sysadmins.lv

"Kiron" <Ki...@HighPlainsDrifter.com> rakstīja ziņojumā
"news:DC7CF498-6F4C-401C...@microsoft.com"...

Kiron

unread,
Mar 6, 2009, 11:26:09 AM3/6/09
to
You're welcome Vadims.
Halting the pipeline and pushing the output down is pretty useful.
Hopefully someone will come up with a way to do this seamlessly, without any juggling, or the PS Team will include such a feature in v3? Looks like it's too late for v2.

v2 Select-Object has a -Skip parameter but, like -First and -Last, the Cmdlet collects everything before outputting the desired amount of objects.

--
Kiron

Josh Einstein

unread,
Mar 6, 2009, 1:04:10 PM3/6/09
to
If they accept that as a bug, then I think they should also make it execute
EndProcessing (unless the break occurred while inside of EndProcessing). My
other post "Any plans for StopProcessing..." talks about the problems this
causes if you count on your End blocks to do cleanup. There should be some
equivalent of a "finally" for pipelines.

Josh

"Shay Levy [MVP]" <n...@addre.ss> wrote in message
news:95d80893704f78...@news.microsoft.com...

rferrisx

unread,
Mar 6, 2009, 4:50:25 PM3/6/09
to
There is a set of methods that work with the pipeline. For example, I
don't understand why return can't be used to assign a value to $MyVal
below:

PS >$i=$null
PS >for (;$global:i++){return $i}
PS >for (;$global:i++){return $i}
2
PS >for (;$global:i++){return $i}
3
PS >write $i
3
PS >foreach-object -process{
$Global:MyVal = for (;$i++){return $i}}
4
PS >foreach-object -process{
$Global:MyVal = for (;$i++){return $i}}
5
PS >write $MyVal

[no value returned]

Josh Einstein

unread,
Mar 6, 2009, 8:01:05 PM3/6/09
to
Ah... for the same reason that if/while/switch/etc don't.

Truthfully it should probably return an error when you try to do that. What
is happening is the return statement is returning from the scriptblock that
you're passing to the ForEach cmdlet. In other words, the foreach statement
does not add a frame to the call stack from which you can return. If you
tried that in C# for example it wouldn't even compile.

private object ForEachCmdlet(this IEnumerable sequence, Func<object> body) {
var x = foreach ( object o in sequence ) { // this line wouldn't
compile
object ret = body(o);
if ( ret != null ) {
return ret; // returns from the method, not the foreach loop
}
}
}

"rferrisx" <rfe...@rmfdevelopment.com> wrote in message
news:a52815f1-e724-4764...@i2g2000prd.googlegroups.com...

Shay Levy [MVP]

unread,
Mar 8, 2009, 5:48:25 AM3/8/09
to

Thanks for voting!

I didn't metion it on my response, the function I posted wasn't for breaking
the pipeline it
was meant to solve your variable assignment.


---
Shay Levy
Windows PowerShell MVP
http://blogs.microsoft.co.il/blogs/ScriptFanatic
PowerShell Toolbar: http://tinyurl.com/PSToolbar


Vv> Hy, Shay!
Vv> I vote on connect. I see that your script only returns first two
Vv> objects,
Vv> but doesn't break a pipeline:
Vv> [vPodans] (measure-command {gwmi win32_ntlogevent -filter
Vv> "logfile='system'"
Vv> | select-first 1}).totalseconds
Vv> 44,5870382
Vv> [vPodans] (measure-command {gwmi win32_ntlogevent -filter
Vv> "logfile='system'"
Vv> | select -first 1}).totalseconds
Vv> 45,6124848
Vv> I will try to find a workaround which helps to acheive all goals. In
Vv> any case - thank you for help!
Vv>
Vv> "Shay Levy [MVP]" <n...@addre.ss> rakst?ja zi?ojum?
Vv> "news:95d80893704f78...@news.microsoft.com"...
Vv>

Shay Levy [MVP]

unread,
Mar 8, 2009, 5:52:44 AM3/8/09
to
Hello Josh,

I agree. The only thing that has to stop (skip) is the process block of the
cmdlet in question, processing should continue to the end block.

---
Shay Levy
Windows PowerShell MVP
http://blogs.microsoft.co.il/blogs/ScriptFanatic
PowerShell Toolbar: http://tinyurl.com/PSToolbar


JE> If they accept that as a bug, then I think they should also make it
JE> execute EndProcessing (unless the break occurred while inside of
JE> EndProcessing). My other post "Any plans for StopProcessing..."
JE> talks about the problems this causes if you count on your End blocks
JE> to do cleanup. There should be some equivalent of a "finally" for
JE> pipelines.
JE>
JE> Josh
JE>
JE> "Shay Levy [MVP]" <n...@addre.ss> wrote in message
JE> news:95d80893704f78...@news.microsoft.com...
JE>

Bob Landau

unread,
Mar 8, 2009, 2:55:00 PM3/8/09
to
I've just added my 2 cents to your feature request.

for what its worth what I've been able to determine is the type being used
to flow the data result from ArrayList::GetEnumerator(). There is however an
override GetEnumerator(int, int) what is missing is how to say this in your
script.

perhaps a

blob | foreach_n <count> { ..... }

would work.

Vadims Podans [MVP]

unread,
Jul 11, 2009, 3:02:18 PM7/11/09
to
I want to add some new things to this conversation:
function Select-First ([int]$n) {
begin {
$Source = $MyInvocation.line
$a = @()
if ($Source -match '^\$(\w+):(\w+)') {$scope = $matches[1]; $var =
$matches[2]}
elseif ($Source -match '^\$(\w+)[^:]') {$scope = 1; $var = $matches[1]}
else {$var = $null}
}
process {

if ($n -eq 0) {
break
} else {
$a += $_
$n--
if ($n -eq 0) {
if ($var) {
Set-Variable $var -Scope $scope -Value $a
(Get-Variable $var).Value
} else {$a}
}
}
}
}

and output:

[↓] [vPodans] 1..5 | Select-First 3
1
2
3
[↓] [vPodans] 1..5 | Select-First 3 | select -First 2
1
2
[↓] [vPodans] $c = 1..5 | Select-First 3
[↓] [vPodans] $c
1
2
3
[↓] [vPodans] $c = 1..5 | Select-First 3 | select -First 2
[↓] [vPodans] $c
1
2
3
[↓] [vPodans]

As previous script this function stream his output to pipeline. And assign
selected data to calling variable and stream output to next pipeline.
However next pipeline doesn't change this variable:
[↓] [vPodans] filter input {$_ * 2 | out-default}
[↓] [vPodans] $c = 1..5 | Select-First 3 | input
2
4
6
[↓] [vPodans] $c
1
2
3
[↓] [vPodans]

here I see that objects are streamed to pipeline, but they lost in pipe
(variable $c will not changed even if data is changed in next pipelines). I
assume that this due breaked pipeline.


--
WBR, Vadims Podans
MVP: PowerShell
PowerShell blog - www.sysadmins.lv

"Kiron" <Ki...@HighPlainsDrifter.com> rakstīja ziņojumā
"news:DC7CF498-6F4C-401C...@microsoft.com"...

Joel Bennett

unread,
Jul 11, 2009, 8:57:44 PM7/11/09
to
That's exactly right, if you break the pipeline, not only are the rest
of the cmdlets not parsed, but assignments statements don't complete
correctly. In PowerShell 1 you get an error message about it:

[5]: $c = 1..5 | select-first 3 | input
2
4
6
The '=' operator failed: System error..
At line:1 char:5
+ $c = <<<< 1..5 | select-first 3 | input
[6]: $c
1
2
3

In Windows 7 RC I'm not seeing the error, but $Error does get a new
instance of System.Management.Automation.BreakException (the text is
just "System Error.")
--
Joel Bennett

Vadims Podans [MVP]

unread,
Jul 12, 2009, 3:31:14 AM7/12/09
to
Yes, V2 console doesn't show errors, however you right, PowerGUI editor show
me errors. I haven't tested this with V1. PowerGUI shows me this:

The pipeline has been stopped.
At :line:1 char:128
+ function PipelineBreakpointerE4078E3092DF4dd9A469F3DC0CBB505C([int]
$offset){BEGIN {} PROCESS {$host.SetShouldExit($offset); $_} <<<< END
{}};$vE4078E3092DF4dd9A469F3DC0CBB505C={Remove-PSBreakPoint -BreakPoint
$bE4078E3092DF4dd9A469F3DC0CBB505C;Remove-Variable
vE4078E3092DF4dd9A469F3DC0CBB505C;Remove-Variable
bE4078E3092DF4dd9A469F3DC0CBB505C;


--
WBR, Vadims Podans
MVP: PowerShell
PowerShell blog - www.sysadmins.lv

"Joel Bennett" <Jay...@HuddledMasses.org> rakstīja ziņojumā
"news:OpiJZvoA...@TK2MSFTNGP05.phx.gbl"...

Robert Robelo

unread,
Jul 12, 2009, 12:54:01 PM7/12/09
to
The way your function simulates -to the user- the assignment by parsing $MyInvocation.Line is pretty good, although assignment to variables with local or private scope modifier won't work but you can fix that.
But the main problem I have with my filters (FirstObj and FirstElements) persists; that is, when Select-First is executed within a srcipt, the script is broken after the call to the function.
How would you work around that?

>> They work well in the console but not in a script, they break out of the
>> script. So I modified them, but to call them inside a script you need to
>> wrap the pipeline in an infinite named loop, pass the loop's label to it
>> so it doesn't break the script:
>>
>> filter FirstObj ([string]$vName = '', $label) {
>> if ($vName) {sv $vName $_ -s 1} else {$_}
>> if ($label) {break $label} else {break}
>> }
>>
>> filter FirstElements ([int]$max = 2, [string]$vName = '', $label) {
>> if ($max -le 0) {break} else {$_arr += ,$_}
>> if (!--$max) {
>> if ($vName) {sv $vName $_arr -s 1} else {$_arr}
>> if ($label) {break $label} else {break}


--
Robert

Vadims Podans [MVP]

unread,
Jul 12, 2009, 1:38:17 PM7/12/09
to
Really I haven't tested this within a script. I will try this. And can you
explain about local and private scope modifiers?

--
WBR, Vadims Podans
MVP: PowerShell
PowerShell blog - www.sysadmins.lv

"Robert Robelo" <Ki...@HighPlainsDrifter.com> rakstīja ziņojumā
"news:ubQBhFxA...@TK2MSFTNGP03.phx.gbl"...

Vadims Podans [MVP]

unread,
Jul 12, 2009, 2:02:10 PM7/12/09
to
Please, can you provide me example scripts code when your filters doesn't
work? I just want to understand existing problems.

--
WBR, Vadims Podans
MVP: PowerShell
PowerShell blog - www.sysadmins.lv

"Robert Robelo" <Ki...@HighPlainsDrifter.com> rakstīja ziņojumā
"news:ubQBhFxA...@TK2MSFTNGP03.phx.gbl"...

Robert Robelo

unread,
Jul 12, 2009, 2:29:15 PM7/12/09
to
The problem with local and private scope modifiers is that the variable will not be available in the parent script. You could check within the first if statement, if $Matches[1] contains either and set the variable's scope and options accordingly to use later in the Set-Variable statement.
Right now, if the user tries the following from the console nothing is assigned to the variable:

# should work
$private:p1 = 1..4
$p1
$local:l1 = 1..4
$l1

# doesn't wok
$private:p2 = 1..9 | Select-First 4
$p2
$local:l2 = 1..9 | Select-First 4
$l2

--
Robert

Robert Robelo

unread,
Jul 12, 2009, 2:51:51 PM7/12/09
to
You replied to my old reply to your original post about breaking the pipeline and returning a value:

# my reply was:
A while back I wrote this filters to stop the pipeline and set the object,
or an array of objects to a variable in the caller's scope:

filter FirstObj ([string]$vName = '') {
if ($vName) {sv $vName $_ -s 1} else {$_}
break
}

filter FirstElements ([int]$max = 2, [string]$vName = '') {
if ($max -le 0) {break} else {$_arr += ,$_}
if (!--$max) {
if ($vName) {sv $vName $_arr -s 1} else {$_arr}
break
}
}

# work fine in the console
1..1gb | ? {!($_ % 17)} | FirstObj v17
1..1gb | ? {!($_ % 19)} | FirstElements 3 arr19
$v17
$arr19.length
"$arr19"

# *adding these scripts to test and see the problem
# but not within a script, try this test scripts
# -< scriptA.ps1 >-
'hi'
1..1gb | ? {!($_ % 89)} | FirstObj v1
$v1
$v1 * 3
'bye'
# -</ scriptA.ps1 >-

# -< scriptB.ps1 >-
'hi'
1..1gb | ? {!($_ % 97)} | FirstElements 3 v2
foreach ($e in $v2) {
$e
$e * 2
}
'bye'
# -</ scriptB.ps1 >-
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - #
.\scriptA.ps1
.\scriptB.ps1

# *my workaround to the problem, break out of an infinite named loop
# They work well in the console but not in a script, they break out of the
# script. So I modified them, but to call them inside a script you need to
# wrap the pipeline in an infinite named loop, pass the loop's label to it
# so it doesn't break the script:

filter FirstObj ([string]$vName = '', $label) {
if ($vName) {sv $vName $_ -s 1} else {$_}
if ($label) {break $label} else {break}
}

filter FirstElements ([int]$max = 2, [string]$vName = '', $label) {
if ($max -le 0) {break} else {$_arr += ,$_}
if (!--$max) {
if ($vName) {sv $vName $_arr -s 1} else {$_arr}
if ($label) {break $label} else {break}
}
}

# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - #
# in the console, no label necessary
1..1gb | ? {!($_ % 13)} | FirstObj v13
1..1gb | ? {!($_ % 17)} | FirstElements 3 arr13
$v13
$arr13.length
"$arr13"

# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - #
# *script does not break, but workaround is cumbersome
# sample scripts
# -< script1.ps1 >-
'hi'
:x while (1) {1..1gb | ? {!($_ % 7)} | FirstObj v1 x}
$v1
$v1 * 3
'bye'
# -</ script1.ps1 >-
# -< script2.ps1 >-
'hi'
:y while (1) {1..1gb | ? {!($_ % 12)} | FirstElements 3 v2 y}
foreach ($e in $v2) {
$e
$e * 2
}
'bye'
# -</ script2.ps1 >-
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - #
.\script1.ps1
.\script2.ps1

--
Robert

Robert Robelo

unread,
Jul 12, 2009, 3:42:17 PM7/12/09
to
Microsoft's NNTP server is misbehaving again. My last replies were lost, try loading them directly...

news:ezl#57xAKH...@TK2MSFTNGP03.phx.gbl
news:e7KfXHyA...@TK2MSFTNGP04.phx.gbl

...or go to Google's

http://groups.google.com/group/microsoft.public.windows.powershell/browse_frm/thread/40356985a4e3e015


--
Robert

Vadims Podans [MVP]

unread,
Jul 12, 2009, 4:13:02 PM7/12/09
to
it's ok, because MS NNTP stores messages only 90 days. Therefore I need to
backup this. I want to share my backup script with others (if any is
interested with this):
$date = (Get-Date).AddDays(-80)
Set-Location "C:\Users\vpodans\AppData\Local\Microsoft\Windows Live
Mail\Microsoft kopienas (1)"
$destfolder = "C:\Users\vpodans\AppData\Local\Microsoft\Windows Live
Mail\Storage Folders\Microsoft Communities"
dir | ?{$_.psiscontainer} | %{$path = Join-Path $destfolder $_.name
if (!(Test-Path $path)) {md $path}
$_ | dir | ?{$_.lastwritetime -lt $date} | copy-Item -Destination $path
}

just put this script to Task Scheduler and have a nice day :)

I have a copy of this conversation and will try again in this.


--
WBR, Vadims Podans
MVP: PowerShell
PowerShell blog - www.sysadmins.lv

"Robert Robelo" <Ki...@HighPlainsDrifter.com> rakstīja ziņojumā

"news:e8r9ijyA...@TK2MSFTNGP03.phx.gbl"...

Robert Robelo

unread,
Jul 13, 2009, 4:02:00 PM7/13/09
to
This filter combines my original filters with your ideas -parse command line and retrieve variable after setting it- plus additional capabilities, i.e. type casting and literal scope modifier. It should work in both v1 and v2*, but the broken script issue remains. In order to not break the script, this time I wrap the statement in a “Do-At-Least-Once” Loop so it breaks out of that and continues execution, but the statement has to be in its own line.

*In v2 you could parse the command line with Management.Automation.PSParser’s Tokenize Static Method.

filter Get-First ([Int]$Quantity = 1) {
begin {
switch ($Quantity) {
{$_ -le 0} {throw '-Quantity must be a positive integer.'}
1 {$Output = ''}
default {$Output = @()}
}
$Patt = '^\s*(\[[\w\.]+(\[\s*\])?\])?\s*\$([\w:]+)\s*='
$Option = 'None'
if ($MyInvocation.Line -match $Patt) {
$Variable, $Type = $Matches[3,1]
if ($Variable -match ':') {
$Scope, $Variable = $Variable.Split(':')
switch -regex ($Scope) {
'Local|Private' {$Scope = 1}
Private {$Option = 'Private'}
}
} else {$Scope = 1}
}
}
process {
trap [Management.Automation.BreakException] {continue}
if ($Quantity -le 0) {break} else {$Output += $_}
if (!--$Quantity) {
if ($Type) {
Invoke-Expression "$Type`$Output = `$Output "
}
if ($Variable) {
Set-Variable $Variable -Scope $Scope -Value $Output -Option $Option
(Get-Variable $Variable -Scope $Scope).Value
} else {$Output }
}
}
}

# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - #

# console
Set-Alias gf Get-First -ea 0
1..1gb | ? {!($_ % 73)} | gf 3
1..1gb | ? {!($_ % 73)} | gf 7 | gf 3
[Int16]$c1 = 1..1gb | ? {!($_ % 73)} | gf 1
$local:c2 = 1..1gb | ? {!($_ % 73)} | gf 3
$private:c3 = 1..1gb | ? {!($_ % 73)} | gf 7 | gf 3
[Single]$c4 = 1..1gb | ? {!($_ % 73)} | gf 1
[Decimal[]]$script:c5 = 1..1gb | ? {!($_ % 73)} | gf 3
[Double[]]$global:c6 = 1..1gb | ? {!($_ % 73)} | gf 7 | gf 3
@"
c1 = $c1
c2 = $c2
c3 = $c3
c4 = $c4
c5 = $c5
c6 = $c6
"@
1..6 | % {iex "`$c$_.GetType().Fullname"}

# script
# -< script1.ps1 >-
$DebugPreference = 'Continue'
Write-Debug Start
Set-Alias gf Get-First -ea 0
do {
1..1gb | ? {!($_ % 73)} | gf 3
} until (1)
do {
1..1gb | ? {!($_ % 73)} | gf 7 | gf 3
} until (1)
do {
[Int16]$s1 = 1..1gb | ? {!($_ % 73)} | gf 1
} until (1)
do {
$local:s2 = 1..1gb | ? {!($_ % 73)} | gf 3
} until (1)
do {
$private:s3 = 1..1gb | ? {!($_ % 73)} | gf 7 | gf 3
} until (1)
do {
[Single]$s4 = 1..1gb | ? {!($_ % 73)} | gf 1
} until (1)
do {
[Decimal[]]$script:s5 = 1..1gb | ? {!($_ % 73)} | gf 3
} until (1)
do {
[Double[]]$global:s6 = 1..1gb | ? {!($_ % 73)} | gf 7 | gf 3
} until (1)
@"
s1 = $s1
s2 = $s2
s3 = $s3
s4 = $s4
s5 = $s5
s6 = $s6
"@
1..6 | % {iex "`$s$_.GetType().Fullname"}
Write-Debug End
# -</ script1.ps1 >-

--
Robert

Robert Robelo

unread,
Jul 13, 2009, 8:42:10 PM7/13/09
to
# previous filter had a couple of bugs

filter Get-First ([Int]$Quantity = 1) {
begin {
if ($Quantity -le 0) {throw '-Quantity must be a positive integer.'}
$Output = @()
$Patt = '^\s*(\[([\w\.]+(\[\s*\])?)\])?\s*\$([\w:]+)\s*='
$Option = 'None'
$Scope = 1
if ($MyInvocation.Line -match $Patt) {
$Variable, $Type = $Matches[4,2]
if ($Variable -match ':') {
$Scope, $Variable = $Variable.Split(':')
switch -regex ($Scope) {
'Local|Private' {$Scope = 1}
Private {$Option = 'Private'}
}
}
}
}
process {
trap [Management.Automation.BreakException] {continue}
if (!$Quantity) {break} else {$Output += $_}
if (!--$Quantity) {
if ($Output.Count -eq 1) {$Output = $Output[0]}
if ($Type) {$Output = $Output -as $Type}
if ($Variable) {
Set-Variable $Variable $Output -Option $Option -Scope $Scope
Get-Variable $Variable -Scope $Scope -ValueOnly
} else {$Output}
}
}
}

--
Robert
0 new messages