PowerShell tips and tricks part #3: Chain of operators

This is translation of my article about some PowerShell tips & tricks not only for developers. I will split the article into more parts, so you won't get tired too early ;)

Operators and variables – chain of operators

This technique is not used very often, but it can sometimes help you make your code more readable and you can avoid calling some cmdlets.
Just for this demo suppose that our directory contains these files:

ch01-2010-03-01.txt
ch01-2010-03-02.txt
ch02-2010-03-01.txt
ch02-2010-03-02.txt
ch03-2010-03-01.txt
ch04-2010-03-01.txt

We would like to get only those that begin with ch01. After that we want to parse only part of the file name that can be converted to [datetime]. You would probably do it like this:

[0] Get-ChildItem c:\temp\aa\ | 
   select -exp Name | 
   ? { $_ -like 'ch01*'} | 
   % { $_ -replace 'ch01-|\.txt','' } 

Looks pretty familiar, right? However, you can also use other approach.
Note that the code select -exp Name is not necessary in this case because [FileInfo] is converted to string. During this conversion file name is returned.
Update: [Fileinfo] is sometimes converted to full path. It depends on how the object was constructed. However, I consider this behaviour rather buggy..

[1] (Get-ChildItem c:\temp\aa\ | select -exp Name)  `
   -like 'ch01*'  `
   -replace 'ch01-|\.txt',''

Explanation

There are two things to highlight:
First – operators can be chained. So, operator replace could be split to two for the sake of readability. The code would then look like this: ...-replace 'ch01-','' -replace '\.txt',''. The result of first operator was used when evaluating the second operator. I haven't seen that documented anywhere. Maybe I wasn't searching hard enough. In case you will find some info about it, please let me know.

Second – some operators work with scalars and some with arrays. That's why we could use arrays as left operand for like and replace and the result were correct values.

Lets go even further with our example. Lets convert values that represent dates to datetime.
This is wrong: ... -replace 'ch01-|\.txt','' -as [datetime]. Why? In this case the operator tries to convert input objects (array) to date and that can't succeed. Anyway, we will change the code only a little and it behave correctly.

Compare:

Get-ChildItem c:\temp\aa\ | 
	select -exp Name | 
	? { $_ -like 'ch01*'} | 
	% { $_ -replace 'ch01-|\.txt','' } |
	% { $_ -as [datetime] } |
	? { $_ -le '2010-03-01' }
(Get-ChildItem c:\temp\aa\) `
	-like 'ch01*' `
	-replace 'ch01-|\.txt','' `
	-as [datetime[]] `
	-le '2010-03-01'

Any disadvantage?
There is only one: you have know that you will use this chaining and begin the command with parenthesis.

Meta: 2010-05-10, Pepa