I'm having problems assessing the depth of nested files within a directory

Hello. I want to create a PowerShell functions which takes a directory full name as parameter, then returns an array which stores arrays which store two values, the depth in which a folder is nested within a directory, and the folder, respectively, for instance, if I have a directory C:\ which contains folders 1,2,3, where folder 4 exists within folder 1, I want the function to return an array equivalent to @(@(1,1),@(1,2),@(1,3),(2,4)), meaning that folders 1,2,3 are in a depth 1 in relation to the directory and the folder 4 is in a depth 2 in relation to the directory. Let’s say that for that I’ve created a function called “GetFolders” which returns an array which stores all the archives of a specific directory. Here is the function:

function GetFolders($Directory)
{
$Files = Get-ChildItem $Directory -Force;
$Folders = @();
for($Q = 0; $Q -$Files.length; $Q++)
{
if(Test-Path -Path $Files[$Q].FullName -PathType Container)
{
$Folders+=$Files[$Q]
}
}
return $Folders
}

Now we have the function I mention in the beginning:

Function AssessDepths($Directory)
{
$Folders = @();
function Recursion($Depth, $Directory)
{
$FolderFolders = GetFolders($Directory);
for($Q = 0; $Q -$FolderFolders.length; $Q++)
{
$FolderFolders[$Q] = @($Depth, $FolderFolders[$Q]);
}
$Folders += $FolderFolders;
for($Q = 0; $Q -$FolderFolders.length; $Q++)
{
Recursion($Depth+1, $FolderFolders[$Q][1].FullName);
}
}
Recursion(1, $Directory);
return $Folders;
}

When I try to scan a directory with it (let’s call it $Directory), by running AssessDepths($Directory), the PowerShell keeps processing the function as if it was stuck in an infinite loop and a virtually endless task which takes a lot of time to be done (which indicates there is likely something wrong in the execution of the code). Why is that happening? As far as I’m concerned the logics of the algorithm is correct, and I’ve the impression I’ve achieved success in achieving my goal using codes similar to that, which makes me to suppose that sometimes this code may work and sometimes this code may not work, as if PowerShell is a problematic programming language, so to say, which behaves in an unpredictable manner sometimes. Furthermore, I’ve realized that even though I may not assign a returning value to my functions AssessDepths and Recursive using the “return” artifice, PowerShell will act as if I did assign a returning value to my functions AssessDepths and Recursive, for instance if, after me creating the function, I type $A = AssessDepths($Directory), and I’ve also noticed that if I type the symbol $ and a variable e.g $Depths and $Folders, then this alters the variables $Depths, $FolderFolders,$Folders, and or the returning value of the function AssessDepths and or Recursive, as if they get confused with each other and as if saying something like “$Depth;” was akin to writing something like “$Depth += $Folders” and “$Folders = $Folders + $Depths”, when for me writing $ + something e.g “$Depth” is just a way of printing a variable in the screen, at least I suppose so. I’m not familiar with Powershell programming, by the way, and I’m used to use Javascript. Thanks.

Random-User,
Welcome to the forum. :wave:t4:

Hmmm … if I got it right you’re overcomplicating this task a lot. Since paths have backslashs you just have to count the backslashs in the fullpaths you striped from the starting path … :man_shrugging:t4: … or did I get something wrong? :wink:

So, something like this should to the trick:

$StartPath = 'D:\sample'
Get-ChildItem -Path $StartPath -Directory -Recurse |
ForEach-Object {
    [PSCustomObject]@{
        Name         = $_.Name
        RelativePath = ($_.FullName).toString().replace($StartPath, '')
        Depth        = ((($_.FullName).toString().replace($StartPath, '')).ToCharArray() -eq '\').count
    }
}

Well … to know what’s going on with your code you should start debugging it. :wink:

Regardless of all that - When you post code, sample data, console output or error messages please format it as code using the preformatted text button ( </> ). Simply place your cursor on an empty line, click the button and paste your code.

Thanks in advance

How to format code in PowerShell.org <---- Click :point_up_2:t4: :wink:

Thanks.

Thanks. Yes. That’s what I want, however I prefer imperative programming rather than declarative programming as I’m a sort of boomer in programming, as I will show the solution I’ve found for the problem below. Do you have an idea whether declarative programming is more efficient than imperative programming for the fact it apparently uses more inbuilt native artifices than imperative programming? How can I assign the results of that part of code into a variable?

Basically here was the problem more or less:

1- When the function Recursion is called with two parameters separated by commas within a parenthesis pair (e.g Recursion(1, $Directory)), the Powershell apparently assumes that the command is providing an array $Depth containing two values that were supposed to be $Depth and $Directory, respectively, while taking the variable $Directory as either having a null value and/or being inexistent (I don’t know if there is a difference between being null and being inexistent, anyways), which can be asserted inserting the debugging commands Write-Output "Depth -> " + $Depth; and Write-Output "Directory -> " + $Directory;, as it can be seen in the image below (PS: $Directory stores a value relative to the full name of a directory) :

EDIT: Image removed due to a request

2 - As such, when the function GetFolders($Directory) is called in order for its returning value to be stored in the variable $FolderFolders, the Powershell apparently runs the function GetFolders with either no paremeter or a null parameter (I don’t know if there is a difference between these things, as I’ve previously said), and when the function GetFolders is called in that condition, it behaves as if it was given the full name of the current directory as a parameter, thereby returning all the folders of the current directory

3- As such, a thing similar to an aforementioned thing happens when the function Recursion is recursively called in the for loop, where the function Recursion just takes the parameter $Depth+1 as valid whereas ignoring the second one. When the function Recursion is called in the loop, the Powershell apparently takes $Depth+1 as the variable $Directory (which was supposed to work as a second parameter in the function Recursion), then the program ends up in an infinite loop, looping within the same directory over and over, with the variable $Depth assuming an odd pattern every time the function Recursion is called, as shown below (Note: I’ve added the following commands in the for loop, above the Recursion call within the for loop:

Write-Output "Depth + 1 -> " + $Depth + 1; Write-Output "FolderFolders[Q][1]FullName -> " + $FolderFolders[$Q][1].FullName;

and PS: I’ve used the Black stripe in the image to cover a directory full name):

[I WILL TRY PUT THE IMAGE IN THE NEXT COMMENT] Edit: I did it however I will remove it due to a request

4- I tried to create a new function, basically, which, using a sort of “JavaScript logics”, things would go well. The function was more or less this one (if not the same)(as I’m typing in this comment the function apparently got formated in a weird way):

function Assess($DirectoryFullName) { $Result = @() function Recursion($DepthsAndDirectories) { $Folders = GetFolders($DepthsAndDirectories[1]); for($Q = 0; $Q -$Folders.length; $Q++) { $Result += $DepthsAndDirectories[0]; $Result += $Folders[$Q]; } $DepthsAndDirectories[0] ++; for($Q = 0; $Q -$Folders.length; $Q++) { Recursion($DepthsAndDirectories[0], $Folders[$Q].FullName); } } Recursion(1, $DirectoryFullName); return $Result; }

However, bad things happened, not only in this code but in the course of me trying to make the function function from this code as a standpoint, such as the fact that $Result += $DepthsAndDirectories[0], instead of adding the depth of a folder to the array $Result, it transforms the array $Result in a number, apparently, because apparently when you add an empty array to a number the empty array becomes a number (so I had to do $Result += @($DepthsAndDirectories[0]), if I’m not mistaken, because apparently when you add the @() thing then the array doesn’t become a number when added to a number), and also the fact the return command wasn’t working according to my “JavaScript” expectations and the variable $Result was apparently either not being added any elements to it or either it was reseted every time the function Recursion was called;

Anyways, I’ve found this code satisfied what I wanted:

function Assess($DirectoryFullName) { function Recursion($DepthsAndDirectories) { $DepthsAndDirectories[0] ++; $Folders = GetFolders($DepthsAndDirectories[1]); for($Q = 0; $Q -$Folders.length; $Q++) { $DepthsAndDirectories[0]; $Folders[$Q]; Recursion($DepthsAndDirectories[0], $Folders[$Q].FullName); } } Recursion(0, $DirectoryFullName); }

I found something like this: Instead of making

`for($Q = 0; $Q -$Folders.length; $Q++)
    {
        $Result += $DepthsAndDirectories[0];
        $Result += $Folders[$Q];
        }`

As I’ve previously done in an attempt to make the function function as I’ve wanted, you could simply write $DepthsAndDirectories[0]; and $Folders[$Q]; (in two different lines, just as $Result += $DepthsAndDirectories[0]; and $Result += $Folders[$Q];, that the PowerShell apparently either automatically assigns it to the “variable” (I’m using quotes because I don’t know if it is precise to call “return” a “variable”) “return” as if you wrote $Result += $DepthsAndDirectories[0]; and $Result += $Folders[$Q];, or it adds the output of these commands in a sort of internal “native” return “variable” so that, by you simply writing these variables, you are able to store them in a seemingly mysterious variable which will serve as a return value for ye. This is weird. I’ve found that apparently outputting variables in Powershell (e.g $Result (if that is considered an outputting command in PowerShell at all)), which I would say would be similar to Console.log in Javascript or simply typing the name of a variable in the browser console and then typing enter in JavaScript, alters the returning value of a function, and that it is not necessary to use the return keyword to have a function to return a value, unlike JavaScript functions which require the return keyword in order to return a value

'The image expires in about 1 Week Edit: Image link removed due to a request

Please do not post images of code or console output. Instead post the plain text and format it as code.

To you post code, sample data, console output or error messages please format it as code using the preformatted text button ( </> ). Simply place your cursor on an empty line, click the button and paste your code.

Thanks in advance

How to format code in PowerShell.org <---- Click :point_up_2:t4: :wink:

1 Like