PowerShell Pipeline

PowerShell enables the output of one command to be piped into the input of another (much like Unix command shells) PowerShell provides operators and Cmdlets that can be used to filter pipeline data.

Perforce Command Line Recipes, in the Public Depot Wiki, contains Unix pipeline examples. I've add their PowerShell equivalents.

The first column following table lists Unix commands commonly used in pipelines. The second column lists their PowerShell counterparts along with PowerShell examples.

Unix Command PowerShell Command
grep Select-String
p4 changes -m100 | select-string 'pkania'
grep -v Where-Object{$_ -notmatch RE}
?{$_ -notmatch RE}
p4 files ... | ?{$_ -notmatch 'change \d+ \(binary'}
lists all the Perforce files under the current directory that aren't binary
sed ForEach-Object{$_ -replace RE,EXPR}
%{$_ -replace RE,EXPR}
p4 changes -ssubmitted -m10 | %{$_ -replace '^Change (\d+).*','$1'}
lists the change numbers of the last 10 submitted changelists
backquote (``) $()
$(p4 changes -m1 -ssubmitted).split()[1]
evaluates to the number of the last submitted changelist
$(p4 label -o pkania-saved-tag) -replace "Created by pkania","Phil's saved work" | p4 label -i
retrieves the label form, replaces the description and save the changes
This idiom is commonly used to update Perforce forms.
Double quotes are used around the expressions above because of the embedded single quote.

$(p4 change -o) -replace '<enter description here>','Nightly build results' | p4 submit -i
See KB Article: Submitting Files Non-interactively
xargs ForEach-Object{}
%{}
p4 changes -ssubmitted '@2009/01/08,@2009/01/09' | %{p4 describe $_.split()[1]}
describes all the changes that were submitted on 1/8/2009
find . -type f Get-ChildItem
gci
gci -recurse | ?{-not $_.PSIsContainer} | %{$_.FullName}
head Select-Object -first n
select -first n
p4 files ....cs | select -first 10
tail Select-Object -last n
select -last n
p4 files ....cs | select -last 10

The Select-String Cmdlet filters its input for strings matching the supplied regular expression much like the Unix grep command.

The -match and -notmatch operators, used with the Where-Object Cmdlet (whose alias is ?), can also be used to filter the pipeline.

The automatic variable $_ contains the current pipeline object in the Where-Object and ForEach-Object script blocks.

The -replace operator, used with the ForEach-Object Cmdlet (whose alias is %), can be used to replace text matching the specified regular expression, much like the Unix sed command.

It's a good idea to get in the habit of quoting regular expression patterns with single quotes ('') instead of double quotes (""). If you use double quotes, PowerShell will attempt to expand and backreferences (e.g '^Change (\d+).*','$1') before passing the pattern to the operators or Cmdlets.

They subexpression operator $() can be used to substitute the output of another command (or pipeline) into a place where an expression is expected. It can be used much like the backquoting (``) characters are used in Unix command shells.

The ForEach-Object Cmdlet can also be used like the Unix xargs command to repeatedly execute a command with arguments from the pipeline.

gci, the alias for the Get-ChildItem Cmdlet, with the -recurse option can can be used to find files much like the Unix find command. You can supply arguments to Get-ChildItem to filter the returned items.

PowerShell strings inherit the methods of the .NET String class. You access these with the dot operator. For example:

PS D:\workspaces\alamimo_ws> $upper = "Mixed Case".ToUpper()

Pattern strings can be cast to regular expression objects. PowerShell regular expression objects inherit the methods of the .NET Regex class.For example:

PS D:\workspaces\alamimo_ws> $re = [regex]'\s+'
PS D:\workspaces\alamimo_ws> $re.Split("one    two     three")

You can also access static methods of .NET classes from within PowerShell. The .NET Regex class provides a static Split method that can split a string using a regular expression. For example:

PS D:\workspaces\alamimo_ws> $words = [regex]::Split("this is a sentence",'\s+')

The Select-Object Cmdlet can also be used like the Unix head and tail commands. It can also be used to construct objects in the pipeline.

To learn more about the Select-String Cmdlet, enter the following at the PowerShell prompt

PS D:\workspaces\alamimo_ws> help Select-String

To learn more about the regular expressions, enter the following at the PowerShell prompt

PS D:\workspaces\alamimo_ws> help about_regular_expression

To learn more about the -match, -notmatch and -replace operators enter the following at the PowerShell prompt

PS D:\workspaces\alamimo_ws> help about_comparison_operators

To learn more about the ForEach-Object Cmdlet, enter the following at the PowerShell prompt

PS D:\workspaces\alamimo_ws> help ForEach-Object

To learn more about the Where-Object Cmdlet, enter the following at the PowerShell prompt

PS D:\workspaces\alamimo_ws> help Where-Object

To learn more about the GetChild-Item Cmdlet, enter the following at the PowerShell prompt

PS D:\workspaces\alamimo_ws> help GetChild-Item

To learn more about the Select-Object Cmdlet, enter the following at the PowerShell prompt

PS D:\workspaces\alamimo_ws> help Select-Object