Nicola Cossu
Nicola Cossu

Reputation: 56397

can I include root folder to get-childitem output programmatically?

If I run this simple command:

gci e:\mytree -r | select fullname

it gives this output:

E:\mytree\folder1                                                                                                                                                                      
E:\mytree\folder2                                                                                                                                                                      
E:\mytree\folder3                                                                                                                                                                      
E:\mytree\file1.txt                                                                                                                                                                    
E:\mytree\file12.txt                                                                                                                                                                   
E:\mytree\folder1\folder.with.dots                                                                                                                                                     
E:\mytree\folder1\folder.with.dots\file inside folder with dots.txt                                                                                                                    
E:\mytree\folder3\file4.doc     

Is there any way to include in the output even root folder, so that I could have

E:\mytree
E:\mytree\folder1                                                                                                                                                                      
E:\mytree\folder2                                                                                                                                                                      
E:\mytree\folder3                                                                                                                                                                      
E:\mytree\file1.txt                                                                                                                                                                    
E:\mytree\file12.txt                                                                                                                                                                   
E:\mytree\folder1\folder.with.dots                                                                                                                                                     
E:\mytree\folder1\folder.with.dots\file inside folder with dots.txt                                                                                                                    
E:\mytree\folder3\file4.doc    

Upvotes: 6

Views: 9061

Answers (6)

JohnLBevan
JohnLBevan

Reputation: 24470

Another option is to just roll a function such as below.

Function Get-ItemTree {
    [CmdletBinding()]
    Param (
        [Parameter(Mandatory = $true)]
        [ValidateScript({if (Test-Path $_ -PathType 'Container'){$true}else{throw "Invalid Path: '$_'.  You must provide a valid directory."}})]
        [String]$Path
    )
    Get-Item -Path $Path
    Get-ChildItem -Path $Path -Recurse -OutBuffer 1000
}

You can add in any parameters you wish to pass through; such as a -Filter argument. Here I've hardcoded the assumption that if using this function you'd want it to be run on a container rather than leaf, you'd want to recurse, and may want to fetch a bunch of files at a time (giving a slight performance gain via the OutBuffer option).

It's not as sexy or clever as other solutions, but should be efficient, easy to reuse, easy to understand, and works for empty containers.

This is similar to your own answer, but has a few differences.

  • Parameter validation is done using the ValidateScript attribute designed for parameter validation.
  • Failed validation throws an error, rather than using Write-Host (a cmdlet you should generally avoid)
  • You build up an array of results, then return it, rather than feeding the output straight to the pipeline. For large directories this means you'll be creating a very large array in memory / you may hit performance issues or run out of memory.
  • You convert each file system object to a PSObject with a full name property, but don't really have a need for that. If you want to reduce the size of objects by removing un-required attributes you can simply pipe the output to Select-Object -Properties FullName or Select-Object -ExpandProperty FullName (the former creating the same output as your current function, the latter returning an array of strings holding the fullname value).

Long term, I've suggest this Enhancement to MS.

Upvotes: 2

MikeV
MikeV

Reputation: 1

Here's my "old School" solution to this problem. For me, it's a lot easier to use and read.

# add all the file Paths to an array so the Parent can be included
$ToUpdate = @()

$FolderToUpdate = Get-ChildItem $DirectorytoChange -Directory

foreach ($Folder in $FolderToUpdate)
{
  #add the paths to the array
  $ToUpdate += $Folder.FullName
}
# Include the Root
$ToUpdate += $DirectorytoChange


foreach ($Path in $ToUpdate)
{
# Do stuff
}

Upvotes: -1

John Anson
John Anson

Reputation: 131

@(gi e:\mytree) + @(gci e:\mytree -r) | select fullname

@(..) forces the return value from each expression to be an array

Upvotes: 7

Daniel Richnak
Daniel Richnak

Reputation: 1604

get-childitem $root -recurse | foreach-object -begin { $arr = @((get-item $root).fullname) } -process { $arr+= $_.fullname } -end { $arr }

Using foreach-object cmdlet's begin switch, we do some work before handling the objects from get-childitem: we create an array and put the filepath of the root in there.

Then for each object in the pipeline, we append its filepath to the array.

Finally, we output the array to the pipeline.

Upvotes: 6

Nicola Cossu
Nicola Cossu

Reputation: 56397

This is the idea I had

function get-tree($folder) {
if (!(test-path $folder)) {
        write-host "$folder doesn't exist"
        return
    }
else {
        $arr = @()
        $Object = New-Object PSObject -Property @{
        fullname = $folder
        }
        $arr+=$object
        gci $folder -r | % {
                              $Object = New-Object PSObject -Property @{
                              fullname = $_.fullname
                              }
                              $arr+=$object 
                            }

    }
$arr  
}

get-tree E:\mytree


E:\mytree                                                                                                                                                                              
E:\mytree\folder1                                                                                                                                                                      
E:\mytree\folder2                                                                                                                                                                      
E:\mytree\folder3                                                                                                                                                                      
E:\mytree\file1.txt                                                                                                                                                                    
E:\mytree\file12.txt                                                                                                                                                                   
E:\mytree\folder1\folder.with.dots                                                                                                                                                     
E:\mytree\folder1\folder.with.dots\file inside folder with dots.txt                                                                                                               
E:\mytree\folder3\file4.doc       

But I'll wait other advices. :)

Upvotes: 0

ravikanth
ravikanth

Reputation: 25810

Update: I read the question again and understand that your requirement is different. Looking at how that can be done, right now. :)

OLD ANSWER

PSParentPath contains the parent folder. If you are referring to root as in E:\, you can get that using root property.

gci C:\Scripts -Recurse | Select FullName, PSParentPath

or in the second case,

gci C:\Scripts -Recurse | Select FullName, root

Upvotes: 0

Related Questions