Filtering files by their metadata (extended properties)

When you run Get-ChildItem or any of its’ aliases, you’ll get back an array of objects, usually System.IO.FileInfo and System.IO.DirectoryInfo (if you have directories too).

The properties displayed are Mode, LastWritetime, Length and Name. Of course there are other properties in the returned objects, but these are the ones that get displayed by default (more on what gets displayed by default and why, in a future post).

You can use the Format-* or the Select-Object cmdlets to output the other properties and their values, or run Get-ChildItem | Get-Member -MemberType Properties to list all the properties in the PowerShell object.

PS C:> Get-ChildItem | Get-Member -MemberType Properties
   TypeName: System.IO.FileInfo
Name              MemberType     Definition                                                                      
—-              ———-     ———-                                                                      
Mode              CodeProperty   System.String Mode{get=Mode;}                                                   
PSChildName       NoteProperty   System.String PSChildName=myFile.txt                                                 
PSDrive           NoteProperty   System.Management.Automation.PSDriveInfo PSDrive=C                              
PSIsContainer     NoteProperty   System.Boolean PSIsContainer=False                                              
PSParentPath      NoteProperty   System.String PSParentPath=Microsoft.PowerShell.CoreFileSystem::C:            
PSPath            NoteProperty   System.String PSPath=Microsoft.PowerShell.CoreFileSystem::C:myFile.txt             
PSProvider        NoteProperty   System.Management.Automation.ProviderInfo PSProvider=Microsoft.PowerShell.Core…
Attributes        Property       System.IO.FileAttributes Attributes {get;set;}                                  
CreationTime      Property       datetime CreationTime {get;set;}                                                
CreationTimeUtc   Property       datetime CreationTimeUtc {get;set;}                                             
Directory         Property       System.IO.DirectoryInfo Directory {get;}                                        
DirectoryName     Property       string DirectoryName {get;}                                                     
Exists            Property       bool Exists {get;}                                                              
Extension         Property       string Extension {get;}                                                         
FullName          Property       string FullName {get;}                                                          
IsReadOnly        Property       bool IsReadOnly {get;set;}                                                      
LastAccessTime    Property       datetime LastAccessTime {get;set;}                                              
LastAccessTimeUtc Property       datetime LastAccessTimeUtc {get;set;}                                           
LastWriteTime     Property       datetime LastWriteTime {get;set;}                                               
LastWriteTimeUtc  Property       datetime LastWriteTimeUtc {get;set;}                                            
Length            Property       long Length {get;}                                                              
Name              Property       string Name {get;}                                                              
BaseName          ScriptProperty System.Object BaseName {get=if ($this.Extension.Length -gt 0){$this.Name.Remov…
VersionInfo       ScriptProperty System.Object VersionInfo {get=[System.Diagnostics.FileVersionInfo]::GetVersio…


But when you use the Windows explorer in details view, you can see that the files contain a lot of other properties (such as Publisher, Rating, Bit rate, Genre, etc. for music files and Camera model, Date taken, Dimensions, Exposure time, etc. for pictures), these are called extended properties.

If you want to list these extended properties in PowerShell, or filter the files in a folder by a value on one of those properties you will have to use the Shell.Application ComObject.

For this purpose exactly, I wrote my own version of the Get-FileMetaData function (based on Ed Wilson’s version described in

function Get-FileMetaData {

        [Parameter(Mandatory = $true,
                   ValueFromPipeline = $true,
                   ValueFromPipelineByPropertyName = $true)]
        [Alias(‘FullName’, ‘PSPath’)]
    begin {
        $oShell = New-Object -ComObject Shell.Application
    process {
        $Path | ForEach-Object {
            if (Test-Path -Path $_ -PathType Leaf) {
                $FileItem = Get-Item -Path $_
                $oFolder = $oShell.Namespace($FileItem.DirectoryName)
                $oItem = $oFolder.ParseName($FileItem.Name)
                $props = @{}
                0..287 | ForEach-Object {
                    $ExtPropName = $oFolder.GetDetailsOf($oFolder.Items, $_)
                    $ExtValName = $oFolder.GetDetailsOf($oItem, $_)
                    if (-not $props.ContainsKey($ExtPropName) -and
                            ($ExtPropName -ne )) {
                                $props.Add($ExtPropName, $ExtValName)
                New-Object PSObject -Property $props
    end {
        $oShell = $null

And you can use it, for example:

dir -Path C:Pictures | Get-FileMetaData | Where-Object { $_.‘Camera maker’ -eq ‘NIKON’ }


dir -Path C:Music -Recurse | Get-FileMetaData | Where-Object { $_.Genre -in @(‘Rock’,‘Pop’) } | Select-Object Path, Genre, ‘Bit rate’



Thanks to Israel Gofman for the PowerShell challenge.