Filters


Filters are essentially the same as functions. The big differences are that: 1) filters are declared using the Filter keyword; and 2) when objects are piped to a filter, the filter executes one time for each object in the pipeline, rather than just one time for the entire pipeline.

Filters make use of the special $_ variable that represents the current pipeline object. Here's an example:

 filter foo {     $_.ProcessName } 

When the output of Get-Process is piped to this filter, the filter executes one time for each object that Get-Process produces. You can see how this differs from a function, which gets all of the objects in one big chunk through the $input variable. The filter can be used just like you might use a function:

 PS C:\> get-process | foo acrotray alg ati2evxx ati2evxx BTSTAC~1 BTTray btwdins 

Because the filter only gets one object at a time from the pipeline, it doesn't need to use a foreach construct the way our earlier function example did.

Functions vs. Filters

The differences between a function and a filter can be summarized as follows:

  • When something is piped to a function, the piped data goes into the special $input variable and the function is executed once.

  • When something is piped to a filter, the filter is executed one time for each object in the piped data. The current object is available in the special $_ variable, and there's no $input variable.

One thing that can make it difficult to understand these differences is that you can write functions that behave exactly the same way filters behave. For example, consider this filter:

 filter ext {     $_.Extension } 

Now, use Get-Childitem to retrieve the child items (files) of the C: drive, and pipe the child items (files) to the newly-created Ext filter:

 PS C:\> get-childitem c: | ext .wsf .sql .BAT .txt .SYS .pdf .log .xml .Log .wsf .log .wsf .log .txt 

As you can see, the Get-Childitems cmdlet returns several child objects - all files - that were piped to Ext. The Ext filter executed one time for each item in the pipeline. For each item in the pipeline, Ext displayed its Extension property.

Let's try the exact same thing with a function:

 function ext2 {     $_.Extension } 

Now run it the same way:

 PS C:\> get-childitem c: | ext2 PS C:\> 

Why is there no output? The answer is because it's a function so it's executed only one time. It's not passed each child item one at a time. Instead, it's passed an entire collection of child objects in one big chunk. So using $_ to access the pipeline object is really accessing that collection, which doesn't have an Extension property.

With this in mind, let's revise our function:

 function ext2 {   foreach ($file in $input) {     $file.Extension   } } 

Now we'll get the same output as with the original filter:

 PS C:\> get-childitem c: | ext2 .wsf .sql .BAT .txt .SYS .pdf .log .xml .Log .wsf .log .wsf .log .txt 

This time the function is taking $input and going through each item inside the function.

Here's another way to write the function to get the exact same result:

 function ext2 {   Process {     $_.Extension   } } 

This time the function is using the special Process script block, which means the function itself is called only once:

 PS C:\> get-childitem c: | ext2 .wsf .sql .BAT .txt .SYS .pdf .log .xml .Log .wsf .log .wsf .log .txt 

The special Process script block automatically takes $input and executes the script block one time for each object within $input, making each object accessible via the $_ variable, which is exactly the same as a filter would do.

So, you may be wondering how to know when you should write a filter and when you should use a function that uses script blocks. Really, it's up to you. Whatever is easier for you to understand and use, then that's the one you should use. A function containing a Process script block is functionally identical to a filter.



Windows PowerShell. TFM
Internet Forensics
ISBN: 982131445
EAN: 2147483647
Year: 2004
Pages: 289

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net