Properties in pipes with multiple cmdlets

This topic contains 4 replies, has 3 voices, and was last updated by Profile photo of Ronny Peperoni Ronny Peperoni 3 months ago.

  • Author
    Posts
  • #67065
    Profile photo of Ronny Peperoni
    Ronny Peperoni
    Participant

    Hi there!

    I have a problem to understand the way PowerShell handles properties in a pipe with multiple cmdlets. Let's have a look at an example. I'd like to have a list of all directories located in C:. The properties I'd like to see are FullName, CreationTime and Owner. I tried it with this one-liner:

    Get-ChildItem C: | Get-Acl | Select-Object FullName, CreationTime, Owner

    This does not work. The two properties FullName and CreationTime are not included in the Get-Acl cmdlet so these properties do not exists anymore when selected.

    I know, there is a way to solve this with ForEach-Object:

    Get-ChildItem C: | ForEach-Object {
        $Owner = (Get-Acl $_.FullName | Select-Object Owner).Owner
        Write-Host $_.FullName
        Write-Host $_.CreationTime
        Write-Host $Owner
        }

    But this is not a very elegant way, imho. Is there a more elegant way to solve this? Maybe with a one-liner?

    Thanks
    LosPollos

  • #67069
    Profile photo of Olaf Soyk
    Olaf Soyk
    Participant

    You can use calculated properties like this:

    Get-ChildItem C: | Select-Object FullName, CreationTime, @{Name='Owner';Expression={(Get-Acl $_).Owner}}
  • #67071
    Profile photo of Joshua Barton
    Joshua Barton
    Participant

    That's a pretty nice way to do it, actually. Though I wouldn't necessarily write-host it if you want to create a re-usable tool.

    You could do:

        function Get-FileOwner () {
            [CmdletBinding()]
            param (
                # Path
                [Parameter(Mandatory)]
                [string]
                $Path
            )
    
            Get-ChildItem -Path $Path | ForEach-Object {
                [PsCustomObject]@{
                    Owner = (Get-Acl $_.FullName).Owner
                    FullName = $_.FullName
                    CreationTime = $_.CreationTime
                }
            }
        }

    That way from then on you only have to do Get-FileOwner -Path C: to get what you want. More than you asked for. Perhaps more than you need. I did take out the Select-Object Owner part because it was unnecessary, but I think you already had a fairly nice solution.

    • #67099
      Profile photo of Joshua Barton
      Joshua Barton
      Participant

      I had just woken up when I wrote that .. in retrospect, I should've used: Get-ChildItem @PSBoundParameters so any of the advanced switches/options like -ErrorAction would follow into that cmdlet. Like: Get-FileOwner -Path C: -ErrorAction SilentlyContinue. Just a note. Hopefully one of the replies here has helped!

  • #67155
    Profile photo of Ronny Peperoni
    Ronny Peperoni
    Participant

    Thanks to both of you!

    @Olaf: Nice way to use the calculated properties! It seems like calculated properties are more powerful than I thought. Thanks for that inspiration! 🙂

    @Joshua: Yes, if I needed more than just Write-Host I would've probably worked with some kind of a way too complex array.. 🙂 I did not knew about [PsCustomObject] yet. It looks like a very interesting thing. I will have a deeper look at it!

You must be logged in to reply to this topic.