MCPMag.com

Sign up for our newsletter.

I agree to this site's Privacy Policy.

Prof. Powershell

Where Did I Put That File? Part 2

Jeffrey Hicks is back with his second part in locating specific files in PowerShell.

Last time we started looking at ways of using WMI and CIM_DATAFILE class to find files locally or remotely. Because there are potentially thousands of files to search, the more specific you can be in your query the better. Today, let's look at a few other techniques.

First, perhaps you want to limit your search to a particular directory.

PS C:\> $filter = "extension='zip' AND path='\\work\\' AND Drive='C:'"
PS C:\> Get-WmiObject -Class CIM_Datafile -Filter $filter  | Select Name

Name
----
c:\work\foo.zip
c:\work\mytest.zip
c:\work\test.zip

This finds all of the ZIP files in the Work directory. But only in the work directory. If I want to include subfolders, I need to change my expression to use wildcards.

PS C:\> $filter = "extension='zip' AND path LIKE '\\work\\%' AND Drive='C:'"
PS C:\> Get-WmiObject -Class CIM_Datafile -Filter $filter | Select Name

Name
----
c:\work\foo.zip
c:\work\mytest.zip
c:\work\resources\articles\adminwebscripting.zip
c:\work\resources\scripts\fixfileprint.zip
c:\work\resources\scripts\folderandextensionreporting.zip
c:\work\resources\scripts\processpeeker.zip
c:\work\resources\scripts\technet-scriptingexchange-demos.zip
c:\work\test\foo.zip
c:\work\test.zip
c:\work\test2\test3\test4\files.zip

Naturally, this will take a bit longer to run. In the WMI query the % acts like a *. Notice I also changed the operator to LIKE. I can be as creative as I need.

PS C:\> $filter = "Filename like '[f|t]%' AND extension='zip' AND path LIKE '\\work\\%' AND Drive='C:'"
PS C:\> Get-WmiObject -Class CIM_Datafile -Filter $filter  | Select Name

Name
----
c:\work\foo.zip
c:\work\resources\scripts\fixfileprint.zip
c:\work\resources\scripts\folderandextensionreporting.zip
c:\work\resources\scripts\technet-scriptingexchange-demos.zip
c:\work\test\foo.zip
c:\work\test.zip
c:\work\test2\test3\test4\files.zip

Now I found all zip files that started with F or T somewhere in Work on drive C:. What about filtering on size?

PS C:\> $filter = "Filename like '[f|t]%' AND extension='zip' AND path LIKE '\\work\\%' AND Drive='C:' AND FileSize >=50000"
PS C:\> Get-WmiObject -Class CIM_Datafile -Filter $filter | Select Name,FileSize

Name                                                                    FileSize
----                                                                    --------
c:\work\test.zip                                                           66736

Remember, WMI uses the legacy operators. This is the same query as before with the addition of finding files larger than 50000 bytes.

Filtering by date is a little trickier because of the ways WMI stores them. If you look at the object, you'll see a datetime stamp like 20130123162731.247877-300. To filter, we need to compare with a similarly formatted datetime string. Here's a little trick to change a date to the WMI format.

PS C:\> $dt = ([wmiclass]"").ConvertFromDateTime("1/1/2013")
PS C:\> $dt
20130101000000.000000-300

Now I can use $dt in my filter.

PS C:\> $filter = "extension='zip' AND path LIKE '\\work\\%' AND Drive='c:' AND LastModified >='$dt'
"
PS C:\> Get-WmiObject -Class CIM_Datafile -Filter $filter  | Select Name,LastModified,@{Name="Modified";Expression={$_.ConvertToDateTime($_.lastmodified)}}

Name                              LastModified                  Modified
----                              ------------                  --------
c:\work\test\foo.zip              20130123162731.249705-300     1/23/2013 4:27:31 PM
c:\work\test2\test3\test4\file... 20130123162752.620186-300     1/23/2013 4:27:52 PM

Just like that I found all the zip files modified since January 1, 2013. This same filter will also work with Get-CIMInstance. Although if you are using that cmdlet, you don't have to do the date conversion.

PS C:\> $filter = "extension='zip' AND path LIKE '\\work\\%' AND Drive='c:' AND LastModified >='1/1/2013'"
PS C:\> Get-CIMinstance CIM_Datafile –filter $filter

The end result will be the same.

Everything I've shown you I ran locally. But it is just as easy to query 1, 10 or 100 remote machines for the same information, or to run the search as a background job.

 

About the Author

Jeffery Hicks is a Microsoft MVP in Windows PowerShell, Microsoft Certified Trainer and an IT veteran with over 20 years of experience, much of it spent as an IT consultant specializing in Microsoft server technologies with an emphasis in automation and efficiency. He works today as an independent author, trainer and consultant. Jeff writes the popular Prof. PowerShell column for MPCMag.com and is a regular contributor to the Petri IT Knowledgebase and 4SysOps. If he isn't writing, then he's most likely recording training videos for companies like TrainSignal or hanging out in the forums at PowerShell.org. Jeff's latest books are Learn PowerShell 3 in a Month of Lunches, Learn PowerShell Toolmaking in a Month of Lunches and PowerShell in Depth: An Administrators Guide. You can keep up with Jeff at his blog http://jdhitsolutions.com/blog, on Twitter at twitter.com/jeffhicks and on Google Plus (http:/gplus.to/JeffHicks)

comments powered by Disqus

Reader Comments:

Add Your Comment Now:

Your Name:(optional)
Your Email:(optional)
Your Location:(optional)
Comment:
Please type the letters/numbers you see above