Prof. Powershell

Contain Yourself

The PSIsContainer property can offer a view into your computer via this PowerShell trick.

I'm sure many of you use the DIR alias on a daily basis. If you're coming from a CMD.EXE background the DIR command is almost second nature. Unfortunately, the PowerShell equivalent, Get-ChildItem (and the related Get-Item cmdlet) have no way of filtering out folders. In the CMD shell, you could easily get a list of only folders with /ad:

C:\>dir c:\test\ /ad
  Volume in drive C has no label.
  Volume Serial Number is 707A-71BD

  Directory of c:\test

12/16/2009 01:52 PM <DIR>  .
12/16/2009 01:52 PM <DIR>  ..
11/05/2009 08:49 AM <DIR>  bin
08/03/2009 11:06 AM <DIR>  common files
09/29/2009 08:08 AM <DIR>  empty
06/18/2009 07:27 PM <DIR>  files
08/03/2009 11:06 AM <DIR>  foo
08/03/2009 11:06 AM <DIR>  foo bar
04/24/2009 10:20 AM <DIR>  foo2
08/03/2009 11:06 AM <DIR>  lexar
08/03/2009 11:06 AM <DIR>  lsi2k8
09/29/2009 08:26 AM <DIR>  nada
11/06/2009 10:55 AM <DIR>  notthere
08/03/2009 11:06 AM <DIR>  polymon
10/01/2009 11:29 AM <DIR>  poweranswer.xml
11/23/2009 04:20 PM <DIR>  team
08/03/2009 11:06 AM <DIR>  tiki
08/03/2009 11:06 AM <DIR>  vmmount
08/03/2009 11:06 AM <DIR>  xlmon_files
              0 File(s)    0 bytes
             19 Dir(s) 35,801,849,856 bytes free

PowerShell doesn't have such a facility. Instead we need to rely on a pipelined expression using Where-Object. The easiest solution, I think, is to take advantage of a property that all file and folder objects possess called PSIsContainer. This property is a Boolean value that returns True if the item is a folder:

PS C:\> dir c:\test | where {$_.PSIscontainer}

  Directory: C:\test

Mode         LastWriteTime    Length Name
----         -------------    ------ ----
d----   11/5/2009  8:49 AM           bin
d----    8/3/2009 12:06 PM           common files
d----   9/29/2009  9:08 AM           empty
d----   6/18/2009  8:27 PM           files
d----    8/3/2009 12:06 PM           foo
d----    8/3/2009 12:06 PM           foo bar
d----   4/24/2009 11:20 AM           foo2
d----    8/3/2009 12:06 PM           lexar
d----    8/3/2009 12:06 PM           lsi2k8
d----   9/29/2009  9:26 AM           nada
d----   11/6/2009 10:55 AM           notthere
d----    8/3/2009 12:06 PM           polymon
d----   10/1/2009 12:29 PM           poweranswer.xml
d----  11/23/2009  4:20 PM           team
d----    8/3/2009 12:06 PM           tiki
d----    8/3/2009 12:06 PM           vmmount
d----    8/3/2009 12:06 PM           xlmon_files

Here's a slightly more complicated expression that essentially gives you a tree view of a folder:

PS C:\> dir c:\test -rec | where {$_.PSIscontainer} | sort Fullname | select Fullname

FullName
--------
C:\test\bin
C:\test\bin\Release
C:\test\common files
C:\test\common files\data a
C:\test\common files\data b
C:\test\empty
C:\test\files
C:\test\foo
C:\test\foo bar
C:\test\foo bar\child
C:\test\foo2
C:\test\lexar
C:\test\lsi2k8
C:\test\nada
C:\test\nada\1
C:\test\nada\1\2
C:\test\notthere
C:\test\polymon
C:\test\poweranswer.xml
C:\test\team
C:\test\tiki
C:\test\vmmount
C:\test\xlmon_files

I'm recursively listing items in C:\Test that are containers, sorting the results by the FullName property and then selecting the same.

And to make sure there's no misunderstanding, the "containerization" does not apply to archive files like zip:

PS C:\> (get-item C:\test\pmodem-0.5.zip).psiscontainer
False

Before we wrap up, let's look at the opposite. If I run this expression:

PS C:\> dir c:\test\f*

I'll get a list of both directories and files that start with f. But suppose I only want to use files. I can filter accordingly:

PS C:\> dir c:\test\f* | where {! $_.PSIsContainer} | measure-object length -sum -max -min -average

Count    : 15
Average  : 11471.4
Sum      : 172071
Maximum  : 65854
Minimum  : 30
Property : Length

The ! is an alias for the -Not operator. Without this type of filtering, my results would be skewed. I'm still hoping a future version of Get-Childitem that incorporates this type of filtering, but in the meantime you'll have to contain yourself.

About the Author

Jeffery Hicks is an IT veteran with over 25 years of experience, much of it spent as an IT infrastructure consultant specializing in Microsoft server technologies with an emphasis in automation and efficiency. He is a multi-year recipient of the Microsoft MVP Award in Windows PowerShell. He works today as an independent author, trainer and consultant. Jeff has written for numerous online sites and print publications, is a contributing editor at Petri.com, and a frequent speaker at technology conferences and user groups.

comments powered by Disqus
Most   Popular