3

Good morning,

I have 3 folders on my desktop that contain a random amount of folders on each one.

  • Folder 1

    • Sub-Folders: "here too", "more stuff", "Ranom stuff", "Something Here"
  • Folder 2

    • Sub-Folders: "and here", "bored", "Here stuff", "here too", "stuff here"
  • Folder 3

    • Sub-Folders: "Hello", "Howdy", "More Stuff here", "Random", "Random here", "Space"

What I'm trying to accomplish: List the sub-folders in each separate columns based off the main folder, like:

SelectionOne      SelectionTwo  SelectionThree    
------------      ------------  --------------    
0: here too       4: and here   9: Hello          
1: more stuff     5: bored      10: Howdy          
2: Ranom stuff    6: Here stuff 11: More Stuff here
3: Something Here 7: here too   12: Random         
                  8: stuff here 13: Random here    
                                14: Space 

Enter Folder Numbers: 3, 14

Then be able to select the corresponding folder by the number selected such as:

# from the 3, and 14 selection it would be the following selected:
'Something Here' 
'Space'

So far, this I can list the folders in separate columns, just not assign an incremented value of the previous column. The other problem I face is attempting to select the correct index number for that array and somehow correlate it to the correct folder? i.e., when I selected 3,14, the corresponding folders from column one and 3 were selected but, it only displays as this as well:

SelectionOne      SelectionTwo  SelectionThree    
------------      ------------  --------------    
0: here too       0: and here   0: Hello          
1: more stuff     1: bored      1: Howdy          
2: Ranom stuff    2: Here stuff 2: More Stuff here
3: Something Here 3: here too   3: Random         
                  4: stuff here 4: Random here    
                                5: Space          

Here's what I have:

$Folder1 = Get-ChildItem -Path 'C:\users\Abraham\Desktop\Number 1'
    $Folders1 = for ($i=0; $i -lt $Folder1.Count; $i++) {
        [PSCustomObject]@{
            FolderNames1 = "${i}: $($Folder1[$i].Name)" 
        }
    }


$Folder2  = Get-ChildItem -Path 'C:\users\Abraham\Desktop\Number 2'
    $Folders2 = for ($i=0; $i -lt $Folder2.Count; $i++) {
        [PSCustomObject]@{
            FolderNames2 = "${i}: $($Folder2[$i].Name)" 
        }
    }

$Folder3  = Get-ChildItem -Path 'C:\users\Abraham\Desktop\Number 3'
    $Folders3 = for ($i=0; $i -lt $Folder3.Count; $i++) {
        [PSCustomObject]@{
            FolderNames3 = "${i}: $($Folder3[$i].Name)" 
        }
    }

$Count = ($Folders1.Count,$Folders2.Count,$Folders3.Count |  Measure-Object -Maximum).Maximum

& {
    for ($i=0; $i -lt $Count; $i++) {
        [PSCustomObject]@{
            SelectionOne   = ($Folders1[$i].FolderNames1 | Format-List | Out-String).Trim()
            SelectionTwo   = ($Folders2[$i].FolderNames2 | Format-List | Out-String).Trim()
            SelectionThree = ($Folders3[$i].FolderNames3 | Format-List | Out-String).Trim()
        }
    } 
} | Format-Table -AutoSize -Wrap

$index = Read-Host -Prompt "Enter Folder Numbers" # Selected 3, 14
$index = $i.Trim() -split ','
    foreach ($i in $index) {

        # here would be correct folder for the corresponding
        # array number.
        # example:

        <#
            # from the selected 3, and 14.
            # the following folders are selected
            'Something Here' 
            'Space'
        #>
    }

Can anyone point me in the right direction?

I feel like this is something that hasn't been done before but, feel like it would be handy for future Posh users.

Abraham Zinala
  • 4,267
  • 3
  • 9
  • 24

1 Answers1

3

Really nice scripting exercise Abraham :) I didn't change much and there is probably a better approach but I think this should work.

So, what changed?

  • First storing the result of for ($i=0; $i -lt $Count; $i++) { ... } before displaying it to console:
$result = for ($i=0; $i -lt $Count; $i++) {...}

$result | Format-Table -Wrap
  • Casting [int[]] to Read-Host, you need to implement a try {} catch {} here:
[int[]]$index = (Read-Host -Prompt "Enter Folder Numbers") -split ',' # Implement Try Catch here
  • The numbering of files / folders, how to remember the last index ?, that one can be done after the first for loop ($rememberI = $i) then on the following loops you just increment $rememberI:
[PSCustomObject]@{
    FolderNames2 = "${rememberI}: $($Folder2[$i].Name)" 
}
$rememberI++
  • Lastly, how to find out the files / folder the user has selected, this is a bit hacky and here is where I think there could be a better approach and I'm not good explaining how this works, I just know it should work :P
[regex]::Match(
    $result.ForEach({$_.PSObject.Properties}).Where({$_.Value -match "^${i}:"}).Value,
    '(?<=: ).*'
).Value

Code

$Folder1 = Get-ChildItem -Path 'C:\users\Abraham\Desktop\Number 1'
$Folders1 = for ($i=0; $i -lt $Folder1.Count; $i++)
{
    [PSCustomObject]@{
        FolderNames1 = "${i}: $($Folder1[$i].Name)" 
    }
}

$rememberI = $i

$Folder2  = Get-ChildItem -Path 'C:\users\Abraham\Desktop\Number 2'
$Folders2 = for ($i=0; $i -lt $Folder2.Count; $i++)
{
    [PSCustomObject]@{
        FolderNames2 = "${rememberI}: $($Folder2[$i].Name)" 
    }
    $rememberI++
}

$Folder3  = Get-ChildItem -Path 'C:\users\Abraham\Desktop\Number 3'
$Folders3 = for ($i=0; $i -lt $Folder3.Count; $i++)
{
    [PSCustomObject]@{
        FolderNames3 = "${rememberI}: $($Folder3[$i].Name)" 
    }
    $rememberI++
}

$Count = ($Folders1.Count,$Folders2.Count,$Folders3.Count |  Measure-Object -Maximum).Maximum

$result = for ($i=0; $i -lt $Count; $i++)
{
    [PSCustomObject]@{
        SelectionOne   = ($Folders1[$i].FolderNames1 | Format-List | Out-String).Trim()
        SelectionTwo   = ($Folders2[$i].FolderNames2 | Format-List | Out-String).Trim()
        SelectionThree = ($Folders3[$i].FolderNames3 | Format-List | Out-String).Trim()
    }
} 

$result | Format-Table -Wrap

[int[]]$index = (Read-Host -Prompt "Enter Folder Numbers") -split ',' # Implement Try Catch here

foreach ($i in $index)
{
    [regex]::Match(
        $result.ForEach({$_.PSObject.Properties}).Where({$_.Value -match "^${i}:"}).Value,
        '(?<=: ).*'
    ).Value
}

Edit

Displaying FullName instead of Name ?

$folderIndex = @{}

$Folders1 = Get-ChildItem -Path 'C:\users\Abraham\Desktop\Number 1' |
ForEach-Object -Begin { $i = 0 } -Process {

    $newName = "${i}: $($_.Name)"

    [PSCustomObject]@{
        FolderNames1 = $newName
    }

    $folderIndex[$newName] = $_.FullName
    $i++

}

$rememberI = $i

$Folders2  = Get-ChildItem -Path 'C:\users\Abraham\Desktop\Number 2' |
ForEach-Object {
    
    $newName = "${rememberI}: $($_.Name)"
    
    [PSCustomObject]@{
        FolderNames2 = $newName
    }
    
    $folderIndex[$newName] = $_.FullName
    $rememberI++
}

$Folders3  = Get-ChildItem -Path 'C:\users\Abraham\Desktop\Number 3' |
ForEach-Object {

    $newName = "${rememberI}: $($_.Name)"

    [PSCustomObject]@{
        FolderNames3 = $newName
    }
    
    $folderIndex[$newName] = $_.FullName
    $rememberI++
}

$Count = ($Folders1.Count,$Folders2.Count,$Folders3.Count |  Measure-Object -Maximum).Maximum

$result = for ($i=0; $i -lt $Count; $i++)
{
    [PSCustomObject]@{
        SelectionOne   = ($Folders1[$i].FolderNames1 | Format-List | Out-String).Trim()
        SelectionTwo   = ($Folders2[$i].FolderNames2 | Format-List | Out-String).Trim()
        SelectionThree = ($Folders3[$i].FolderNames3 | Format-List | Out-String).Trim()
    }
} 

$result | Format-Table -Wrap

[int[]]$index = (Read-Host -Prompt "Enter Folder Numbers") -split ',' # Implement Try Catch here

foreach ($i in $index)
{
    $thisVal = $result.ForEach({$_.PSObject.Properties}).Where({$_.Value -match "^${i}:"}).Value
    $folderIndex[$thisVal]
}
Santiago Squarzon
  • 41,465
  • 5
  • 14
  • 37
  • 1
    Oh man, this is such a clever way of doing this!:) – Abraham Zinala Aug 12 '21 at 16:11
  • 1
    @AbrahamZinala lol you think? I'm not so convinced on the last part, finding out with `regex` what the user selected, I was hoping to see an answer from mklement0 hehe he is more clever than us – Santiago Squarzon Aug 12 '21 at 16:14
  • 1
    Yeah, honestly thought it was him who had answered! Good stuff man:) – Abraham Zinala Aug 12 '21 at 16:21
  • 1
    @AbrahamZinala _he's our mentor :P_ ... thanks! you too, loved this question, well detailed and explained. – Santiago Squarzon Aug 12 '21 at 16:23
  • 1
    Definitely earned the title of "*Powershell Pops*" x). Mentor and Sensei. – Abraham Zinala Aug 12 '21 at 16:24
  • 1
    how would you go about swapping the numbers selected for the folders full path? Thought I had gotten it to work using the folder matching, but it just keeps being inconsistent. – Abraham Zinala Aug 12 '21 at 17:45
  • 1
    @AbrahamZinala sorry for the delay, was super busy. I'm not 100% sure I understand what you mean, see my last edit. Is that what you want? – Santiago Squarzon Aug 12 '21 at 18:31
  • 1
    Oh man my fault, there were just duplicate entries and was confused when I tried it my way, but yes. That's exactly what I meant, thank ya!:) – Abraham Zinala Aug 12 '21 at 18:38
  • 1
    @AbrahamZinala if you are looking for something like that I would change the approach completely. See my last edit, I would def use a hashtable in that case – Santiago Squarzon Aug 12 '21 at 18:43
  • 1
    That just lets me know that i got a lot more to learn. That's perfect! Changed the vairables as well removing the *s* from `$Folders1` so it could be read properly with your new modified code. – Abraham Zinala Aug 12 '21 at 20:29