Create objects with custom properties containing derived filesystem path information and export them to a CSV – calculated properties

The [System.IO.FileInfo] instances returned by Get-ChildItem for files do not have Folder or FolderName properties.

Get-ChildItem -File $HOME\Desktop | Get-Member, for instance, will show you the available properties, and will show you that the desired information can be derived from the PSPath and PSParentPath properties.

Select-Object allows hashtable-based property definitions, so-called calculated properties, which allow you to rename and/or transform properties and/or add custom properties derived from other property values by way of a script block.

Note: You can also use calculated properties with the Format-Table and Format-List cmdlets for creating output for display only (as well as with other cmdlets – see the linked help topic).

A simplified example of what you’re looking for (includes output to a CSV file):

Get-ChildItem $HOME\Desktop | Select-Object Name,
  @{ Name="Folder"; Expression = { Convert-Path $_.PSParentPath } },
  @{ Name="Foldername"; Expression = { ($_.PSPath -split '\\')[-2] } } |
    Export-Csv Out.csv -Encoding Utf8 -NoTypeInformation

Note that, alternatively, you could add Folder and FolderName properties to the input objects via Add-Member, as you did with the Owner property in your question.

Explanation:

Note that you can get more detailed information about any of the commands mentioned by running Get-Help <command-name> -Full; add -online to view the help topic in a browser; to learn more about the -split operator, run Get-Help about_split; to learn about PowerShell’s help system in general, run Get-Help Get-Help -online.

  • Each @{ ... } construct passed to Select-Object is a hash table that defines a property to attach to each output object:

    • The hash table must have two entries:
      • Name or Label, which defines the property’s name; for brevity, you may use a (case-insensitive) prefix of the key name, such as just n or l.
      • Expression, which defines the property’s value; again, a (case-insensitive) prefix of the key name works too, such as just e.
        • The expression can be a mere property name (a string), in case you simply want to rename an input property, but is more typically a script block ({ ... }), which is a piece of code that gets executed for each input object, and whose output becomes the value of the property being defined; inside that script block, automatic variable $_ (or $PSItem) refers to the input object at hand.
  • Definition of the Folder property: Convert-Path $_.PSParentPath converts the fully qualified PowerShell path that the PSParentPath property contains – which includes a prefix identifying the drive provider – to a regular filesystem path; e.g., Microsoft.PowerShell.Core\FileSystem::C:\Users\jdoe\Desktop -> C:\Users\jdoe\Desktop.

  • Definition of the Foldername property: ($_.PSPath -split '\\')[-2] splits the full path into components by path separator \, and then accesses the next-to-last component (-2), which is the parent folder name; e.g., C:\Users\jdoe\Desktop\file.txt -> Desktop

    • '\\' must be used to represent \, because -split‘s 1st RHS operand is a regular expression, where \ has special meaning and must therefore be doubled to be taken as a literal.
    • If you wanted to support / as the path separator as well for cross-platform support, you’d use ($_.PSPath -split '[\\/]')[-2].
  • Export-Csv exports the objects output by Select-Object to CSV Out.csv, where the input objects’ property names become the header row, and the property values the data rows.

    • -Encoding Utf8, required in Windows PowerShell only (PowerShell (Core) 7+ now fortunately consistently uses BOM-less UTF-8), ensures that non-ASCII characters are properly encoded; by default, Export-Csv uses ASCII encoding and simply replaces non-ASCII characters, such as foreign letters, with verbatim ? characters, resulting in loss of information; note that -Encoding Utf8 in Windows PowerShell invariably creates UTF-8 files with a BOM.

    • -NoTypeInformation, again required in Windows PowerShell only, suppresses a line that Export-Csv by defaults adds as the first line of the output file, which contains the full type name (class name) of the input objects (e.g., #TYPE System.Management.Automation.PSCustomObject; this is meant to facilitate later reconversion into objects).

Leave a Comment