pencilCake
pencilCake

Reputation: 53303

How can I sort the child items from the deepest sub folder to highest one?

I try to get the files of a folder together with the files in its subfolders by doing:

$files = Get-ChildItem "d:\MyFolders" -recurse

QUESTION: How can I sort the $files by their folder hierarchy meaning the deepest files will be at the top in the array and the upper most one will be the last element?

P.S : The reason is if I rename some folders than the path of the files under those renamed ones will be invalid. So I want to process the deepest ones first and move to upper files.

Upvotes: 5

Views: 4631

Answers (2)

Gruntzy
Gruntzy

Reputation: 443

A way to do this is to parse your directory level by level : you start with a list of directories to check (initially, you just have your start folder in the list). Then, for each folder in the list check all direct children : write the files in a result file, add the folders in a "next folders" list.

Do it again with your "next folder" list until this list is empty.

You will get a result file with your file sorted by depth (OK, deepest files are the last in the file, so you'll have to reverse it, but it is sorted by depth anyway :)

This can be done recursively this way :

function Parse-ByDepth ($dirs, $resultfile) {
    $nextdirs=@()

    # if you also want the folders names in the result file
    # write their names in the result file
    $dirs |% {
      echo "$_" >> $resultfile
    }

    # Parse each directory in the list
    foreach ($dir in $dirs){
        # note that the get-childitem here is non recursive.
        # only one level is checked.
        Get-ChildItem $dir | % {
            if ($_.getType().Name -eq "FileInfo") {
               # If the item is a file, append it to the result file
               echo "$($_.FullName)" >> $resultfile
            }else {
               # if it is a folder, add the folder path to the "next folders" list
               $nextdirs+=$_.FullName
            }
        }
    }
    # once all the item of the current level have been parsed, check if the list is empty
    if ($nextdirs.Length -gt 0) {
        # if the list contains more folder, parse them
        Parse-ByDepth $nextdirs $resultfile
    }
} 

then, you can call the function this way :

$initdir=@("d:\MyFolders")
$resultfile=C:\result_by_depth.txt
Parse-ByDepth $initdir $resultfile

Upvotes: 0

ojk
ojk

Reputation: 2542

It's not specifically sorted by depth, but it will group folders in the same parent together, because of the sorting.

$files | Sort-Object -Descending FullName | Select-Object FullName

If you really need to sort by folder depth, you can do it like this:

$files | Select-Object FullName, @{Name="FolderDepth";Expression={$_.DirectoryName.Split('\').Count}} | Sort-Object -Descending FolderDepth,FullName

Just remove -Descending if you want to reverse the sorting.

Upvotes: 9

Related Questions