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 calculated 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).