Get-ChildItem -filter or -include..when, why and how ?


I did a quick PowerShell training and one of the attendees did some question to me about –filter and –include parameters in the  get-childitem. I will reproduce his questions with my answers :

Q – What is the difference between –filter and –include ?

R – The parameter filter is implemented by the Provider and the parameter include by PowerShell.

Q – And……?

R – This means that Include is a “general way” to search in all providers. Filter is unique implemented by the provider and for this reason faster that Include.

Q-Then, I cannot use filter in all drives ?

R – No, just in the drives that have a provider that support the filter.

Q- How can I know what providers have  filter support ?

R – Use the cmdlet Get-PSprovider to get a list of all providers, then in the column Capabilities you will see what this provider supports..or what it can do.  See:

image

The only provider that accepts Filter is the filesystem provider.

Q – Hummm..then if I wan to find a specific registry  key or a variable, I need to use the include  parameter ?

R – Yes. Lets use the Variable drive that is implemented by the Variable provider. First lets create a variable :

$Jedi = ‘Yoda’

$Sith = ‘Darth Vader’

Then lets connect to the variable drive:

cd variable:  #or set-location variable:

If we try :

Get-ChildItem –filter Jedi –recurse

Get-ChildItem : Cannot call method. The provider does not support the use of filters.
At line:1 char:14
+ Get-ChildItem <<<<  –filter Jedi
    + CategoryInfo          : NotImplemented: (:) [Get-ChildItem], PSNotSupportedException
    + FullyQualifiedErrorId : NotSupported,Microsoft.PowerShell.Commands.GetChildItemCommand

but if we try :

Get-Childitem –include Jedi –recurse

PS Variable:\> Get-Childitem –include Jedi –recurse

Name        Value
—-        —–
Jedi        Yoda

Also –include parameter is a string[] type, then it accepts a string array :

PS Variable:\> Get-Childitem –include Jedi,Sith –recurse

Name   Value
—-   —–
Jedi   Yoda
Sith   Darth Vader

The same with SQLServer provider. It only accepts include. Lets use our Database PowerShell to test it. We have 3 tables called PoshTraining1,PoshTraining2 and PoshTraining3 and 2 stored procedures called sp_PoshTraining1 and sp_PoshTraining2

Lets connect to the SQLServer drive:

cd sqlserver:

Now, in the root lets search for this objects:

get-ChildItem –include *poshtraining* –recurse | format-list schema,name, pspath

image

By the pspath I know what object it is.

we can also split the select to get the second last value in the pspath , that is the object type :

get-ChildItem –include *poshtraining* –recurse |
select  schema,
        name,
        @{E={($_.pspath -split ‘\\’)[-2]};N= ‘ObjectType’}

image

Q – There is some property to know the Object Type unless to use the split ?

R – I don’t know, need to check the properties using Get-Member :

get-ChildItem –include *poshtraining* –recurse | Get-Member

Q – Why are you saying that connect to drive and not to the provider ?

See. The provider is a .net program that allow to us use the data as mounted drives. We can connect to the provider mounting  a drive or a PowerShell Provider Drive –PSDrive. If you see in the providers, we have the Variable and FileSystem provider. You can use the Variable provider because PowerShell has a drive called variable implemented in the Variable Provider, then you are connecting at the Variable drive when use cd variable:

image

If you cannot connect to the provider itself. As you can see in the Filesystem provider, it has its drives : c:\, d: and e:. You only can connect to the drives that are associated with this provide. If you try to connect the FileSystem provider :

PS Variable:\> cd filesystem:
Set-Location : Cannot find drive. A drive with the name ‘filesystem’ does not exist.
At line:1 char:3
+ cd <<<<  filesystem:
    + CategoryInfo          : ObjectNotFound: (filesystem:String) [Set-Location], DriveNotFoundException
    + FullyQualifiedErrorId : DriveNotFound,Microsoft
.PowerShell.Commands.SetLocationCommand
 

[UPDATED with Master Jedi Kirk Munro comments. Yes..you can connect to the provider directly . See his comments below] THANKS A LOT Kirk Alegre

Q – You told that is faster to use filter than Include (when possible)..so,using this idea,  it is faster to use the parameters rather than where-object ?

R – Exactly. In this case you are avoiding the pipeline streaming that may be slow in some cases. Although knowing how to work with the pipeline and effectively know how to  use it , IMHO  is the main concept to a real programming in PowerShell, there is some cases that avoiding the streaming you will have a higher performance. This is one of this cases.

After these questions, I realized that I need to create a chapter in my training specific to PowerShell Drives and Providers. Not only the mention that I was doing. 

As a friend told me, the better way to learn is  teaching Alegre

About Laerte Junior

Laerte Junior Laerte Junior is a SQL Server specialist and an active member of WW SQL Server and the Windows PowerShell community. He also is a huge Star Wars fan (yes, he has the Darth Vader´s Helmet with the voice changer). He has a passion for DC comics and living the simple life. "May The Force be with all of us"
This entry was posted in Powershell, Virtual Pass BR. Bookmark the permalink.

9 Responses to Get-ChildItem -filter or -include..when, why and how ?

  1. Nicely Explained !
    The Questions and their Answers as it goes….makes the topic clearer.

  2. Kirk Munro says:

    Hi Laerte,

    Great article. There is one point you make near the end that isn’t accurate though. When you talk about connecting to drives or providers, you indicate that you connect to drives for the FileSystem provider, but for providers like Variable, Alias, Function, etc., you connect to the provider. That’s actually not true. When you set the location to Variable:, you’re setting the location to a drive named Variable, not to the Variable provider. The same holds true for setting the location to Alias: or Function:.

    Some providers come with a single built-in PSDrive that has the same name as the provider itself. Alias:, Function:, Variable:, and WSMan: are examples of the drives that match perfectly to the provider name. Others have one or more PSDrives with names that do not match the name of the provider itself that connect to a location inside of the provider, or that connect to the root of the provider. Examples of these include the Env: drive which connects to the root of the Environment provider, the Cert: drive which connects to the root of the Certificate provider, the C: drive which connects to the C: location in the FileSystem provider, and the HKLM: drive which connects to the HKEY_LOCAL_MACHINE location in the Registry provider.

    Also you can connect to providers directly, without using drives at all. For example, what would you do if you wanted to set the location to the root of HKEY_LOCAL_MACHINE? You could do either of the following:

    cd HKLM: # Use the PSDrive to go directly to the mapped location

    cd Registry::HKEY_LOCAL_MACHINE # Use the provider to go to the explicit location whether it is mapped or not

    That second example shows how you can access provider locations without drives, and it is important to know you can do this in PowerShell. What if you wanted to see all child items in HKEY_USERS? You can’t use drives for this out of the box, because there is no HKU: drive. Instead you can access that hive using the Registry provider directly. First, look at the hives available in the Registry like this:

    dir Registry:: # Note the double-colon…this is how you access providers.

    Once you run that, you’ll see the locations available in the root of the provider. Then you can see child items in HKEY_USERS like this:

    dir Registry::HKEY_USERS

    This double-colon syntax applies to all providers, allowing you to access content without drives. It isn’t implemented the same for every provider though. For example, you cannot see the local drives on a system by running this command:

    dir FileSystem:: # This raises an error

    I think that’s about the only exception I’ve come across though.

    When does all of this matter? It matters when you:
    a) want to access a path that isn’t available as a PSDrive by default (in which case you can create the PSDrive and then access the path, or just access it directly instead if you don’t want to leave a PSDrive crumb behind)
    b) want to access a path independent of a PSDrive (because PSDrives can be removed — even if it is very unlikely that someone would remove them, it can be done, and someone may have done that as part of their profile, so if you want to be really cautious you can use full Provider paths).

    Sorry for the long-winded comment…I just wanted to illustrate that there are differences between accessing providers and drives so that you can share that information when appropriate in future classes you teach.

    Kirk out.

    • Very Nice my friend. Thanks a LOT for your comments 🙂 Much appreciated . I think that my English is not so good, but what I wanted to say in “but for providers like Variable, Alias, Function, etc., you connect to the provider” is that you are not connecting to the provider, but in the drive associated to this provider, that has the same name. Also good to know man. So far I thought that you cannot connect to the provider directly. Updating my training 🙂

      • Kirk Munro says:

        My pleasure Laerte. I came across this little nugget inside a script that shipped with one of the Microsoft products (I forget which now). Quite useful. One thing I forgot to add was that you can use this for the file system provider as well. e.g.

        cd FileSystem::C:\Windows

        After re-reading my comment, I felt that the example I gave about dir FileSystem:: not working might make someone think that they can’t use provider paths for the FileSystem provider, but they can. You just need to know the drive letters on the system first. 🙂

  3. @sqlchow says:

    The double colon syntax is used for referring to .NET assemblies right? So, can I browse the assemblies using Dir?

    • Kirk Munro says:

      Double-colon is used to reference static properties and methods on .NET types, not assemblies. I think this is what you’re referring to. For example:

      [string]::Empty

      Just because double-colons are used there though, that’s entirely different from PowerShell providers. You can browse providers using dir, not types. To see what’s available on types, you should use tab completion in the native console or Intellisense in PowerShell ISE 3.

  4. Klaas says:

    Hi Laerte

    This is very interesting.
    I tried a Get-ChildItem with -filter to my backup folder. When executed in SQLPS this failed. Now I know it’s because of “provider does not support the use of filters”. So I added a Set-Location C: before the Get-Childitem, hoping it will use the filesystem provider. Strangely, in SQLPS it works, but when used in the command of a jobstep it keeps saying ‘syntax error’. How can I make that work to?

Leave a reply to Kirk Munro Cancel reply