Reputation: 53303
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
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
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