Use PowerShell to Explore Nested Directories and Files

Use PowerShell to Explore Nested Directories and Files

  • Comments 3
  • Likes

Summary: The Microsoft Scripting Guy talks about using the Get-ChildItem cmdlet to find, sort, and count folders.

Microsoft Scripting Guy, Ed Wilson, is here. In the summer, one’s heart turns to, well, numbers if one happens to work for Microsoft. Yes, it is review season. During review season, one has to figure out everything he (or she) has done during the previous year. So if you are a Scripting Guy, part of that has to do with how many Hey, Scripting Guy! Blog posts you wrote, how many Windows PowerShell scripts you wrote, how many screenshots you took, and so on. Luckily, they do not ask how many Tim-Tams I ate or how many cups of tea I drank. (I could probably figure it out, but I would not be able to use Windows PowerShell to do that. We have not yet written a kitchen provider). Today I am going to answer the question of how long have I been writing the Hey, Scripting Guy! Blogs.

Three secrets to using the Get-ChildItem cmdlet

When you use the Get-ChildItem cmdlet, there are three things you must know that are not immediately obvious:

  1. Use the force parameter to view hidden or system files.
  2. Use the recurse parameter to see subdirectories and nested files.
  3. Use the psIsContainer parameter to see only directories.

In the output shown here, the dir command (an alias for the Get-ChildItem cmdlet) returns only a few items.

PS C:\> dir

 

    Directory: C:\

 

Mode                LastWriteTime     Length Name

----                -------------     ------ ----

d-r--         7/22/2012   7:18 AM            data

d----         7/21/2012  11:41 AM            files

d----         7/23/2012   5:52 PM            fso

d----         7/22/2012   8:55 PM            Intel

d----         7/14/2012   9:48 AM            PerfLogs

d-r--         7/22/2012   8:55 PM            Program Files

d-r--         7/22/2012   8:55 PM            Program Files (x86)

d----         7/22/2012   5:33 PM            trans

d-r--         7/22/2012   8:56 PM            Users

d----         7/23/2012  11:26 AM            VMs

d----         7/22/2012   8:56 PM            Windows

Use the Force to see hidden and system files

On the other hand, when I use the force parameter, many more items return. This action corresponds with the Show hidden and system files options in the folder view tool for Explorer. The thing is, this is an easy switch to forget, and one that really makes you feel foolish when someone reminds you of that oversight. It is a Homer Simpson doh! moment. This command is shown here.

Dir -force

The command the output associated with the command are shown in the image that follows.

Image of command output

Burrow into nested folders

If I need to burrow down into a directory structure, I need to use the recurse parameter. If I go back to my previous command from the root of the C:\ drive, and I add the recurse switch, it will return every single file on the entire computer hard disk drive, and will therefore take a bit of time. If, for example, I change to the ScriptingGuys folder, and I use the recurse parameter, I might use a command such as the one shown here.

Get-ChildItem -Path C:\data\ScriptingGuys -recurse

The output from the command begins by listing all of the folders under the ScriptingGuys folder. Then it lists files that appear in the root of the ScriptingGuys folder. When that process completes, it begins to burrow into the other folders. The command and the initial output from the command are shown in the image that follows.

Image of command output

Finding only folders or directories

To only return folders (or directories…or whatever we call them), use the psIsContainer property. This property returns a Boolean value, and it is therefore easy to toss into a Where-Object filter. The command to return only folders within my ScriptingGuys directory is shown here.

Get-ChildItem -Path C:\data\ScriptingGuys -recurse | where {($_.psiscontainer)}

In Windows PowerShell 3.0, the command is simplier due to leaving off the braces and the $_ character. The syntax is shown here.

Get-ChildItem -Path C:\data\ScriptingGuys -recurse | where psiscontainer

The command to return nested folders and the associated output are shown here.

Image of command output

I create a folder each week for my Hey, Scripting Guy! blogs. Suppose I want to know how long I have been writing the Hey, Scripting Guy! Blogs. One way to get this information is to figure out how many folders I have. Because I use a Windows PowerShell script to create and name my folders, I am assured that they are all named the same. (I wrote the script after I became the Scripting Guy, so a few of the first folders are not all capitalized the same.) To do this, I use the Get-ChildItem cmdlet to find the folders, and I pipe the resulting DirectoryInfo objects to the Measure-Object cmdlet. This command is shown here.

PS C:\> Get-ChildItem -Path C:\data\ScriptingGuys -recurse | where {($_.psiscontainer)}  |

Measure-Object

Count    : 289

Average  :

Sum      :

Maximum  :

Minimum  :

Property :

But as we saw, there are folders that do not begin with HSG in the 289 folder count. I created these extra folders for things like the Scripting Games. So to remove them from the count, I use a simple Regular Expression pattern (‘^HSG’). The carrot here means that the folder name does not begin with the letters HSG—so that would be all of my Scripting Games folders and associated folders for articles that are not related to the Hey, Scripting Guy! Blog.

Note   This points to the value of using a Windows PowerShell script to do routine admin tasks. You can be certain that they are all accomplished in the same manner, and it gives you great value when you later need to use a script to gather that information.

The resulting command to find all of the folders that are not HSG folders is shown here.

PS C:\> Get-ChildItem -Path C:\data\ScriptingGuys -recurse | where {$_.psiscontainer

-AND $_.name -notmatch '^hsg'} | measure

Count    : 75

Average  :

Sum      :

Maximum  :

Minimum  :

Property :

Note   Because I did not specify a case sensitive search, the pattern ^hsg works the same as ^HSG.

I now subtract the original number of folders from the non-HSG folders, and arrive at the answer as to how long I have been writing the Hey, Scripting Guy! Blog. The results are in the image shown here.

Image of command output

Playing with Files Week will continue tomorrow when I explore some more cool stuff.

I invite you to follow me on Twitter and Facebook. If you have any questions, send email to me at scripter@microsoft.com, or post your questions on the Official Scripting Guys Forum. See you tomorrow. Until then, peace.

Ed Wilson, Microsoft Scripting Guy 

Your comment has been posted.   Close
Thank you, your comment requires moderation so it may take a while to appear.   Close
Leave a Comment
  • Hi Ed,

    a nice article about the secrets of the "get-Childitem" CmdLet!

    But .. if I may dare to ask the question ... why don't we just count the matching  folders and divide them by the number of weeks per year? Like:

    (Get-ChildItem -Path C:\data\ScriptingGuys -recurse | where {$_.psiscontainer -AND $_.name -match '^hsg'} | measure) / 52

    This would optimize the runtime ... wouldn't it *ssss* :-)

    And I'm still convinced that the introduction of -Directory ( -File, -Link, ... ) switch would help, if it were available for the "Get-ChildItem" CmdLet!

    Klaus.

  • correction:

    I've been to fast ( and too furious :-) I missed  to add the "Count" property in the end!

    (Get-ChildItem -Path C:\data\ScriptingGuys -recurse | where {$_.psiscontainer -AND $_.name -match '^D'} | measure).count / 52

    Klaus.

  • @K_Schulte certainly I could divide by 52 ... and that would work for my specific scenario, but might not help out someone else who did not have as structured a filesystem. In PowerShell 3.0 there is a -directory switch that will return only directories, and there is a -file switch that will return only files. In addition, there is a -attributes that allows you to specify specific file attributes, as well as a -hidden, -readonly and -system switches. There is no -link switch however.