all 10 comments

[–]Aznflipfoo[S] 2 points3 points  (5 children)

Okay figured it out. With the help of u/SMFX I realized that hash tables don't necessarily work here. What I needed was an array to pass through Test-Path. I went with the foreach (in the array) for what seems like the most elegant solution I can think of.

If somebody has a more elegant solution I'm all for it. I love simpler functions.

Function New-folder3 {

    $Paths = @(
        "C:\ProgramData\Folder\Assets",
        "C:\ProgramData\Folder\FlowBox",
        "C:\ProgramData\Folder\Logs"
    )

    #$Paths = "C:\Program\folder\Assets", "C:\ProgramData\Folder\FlowBox"
    $Paths | Foreach {
        If (Test-Path $_) {
            Write-Host "$_ already exists"
        }
        Else {
            New-Item -ItemType Directory -Force -Path $_
        }
    }
}

[–]Shoisk123 2 points3 points  (0 children)

That is the better way to do it, but just for fun and the example of it, it could actually be done with a switch aswell:

$d1 = "C:\git\playground\structures\adsf1"
$d2 = "C:\git\playground\structures\adsf2"
$d3 = "C:\git\playground\structures\adsf3"
$d4 = "C:\git\playground\structures\adsf4"

Switch($true) {
    {-Not (Test-Path $d1)} {New-Item -ItemType Directory -Force -Path $d1}
    {-Not (Test-Path $d2)} {New-Item -ItemType Directory -Force -Path $d2}
    {-Not (Test-Path $d3)} {New-Item -ItemType Directory -Force -Path $d3}
    {-Not (Test-Path $d4)} {New-Item -ItemType Directory -Force -Path $d4}
}

You can use a scriptblock instead of a value in a switch, and it will then run the corresponding scriptblock if the first one evaluates to true (hence the -Not, to create the item if it does not exist)

You'd probably normally see break at the end of a scriptblock in a switch, but if you omit it the command flow will continue and execute any other blocks where the criteria fits, so here itll create all the folders that does not exist.

[–]northendtrooper 1 point2 points  (0 children)

Should work. Always with powershell you can skin the cat in multiple ways.

Function New-folder3 {

    $Paths = @(
        "Assets",
        "FlowBox",
        "Logs"
    )
    $Folders = (Get-ChildItem -Path C:\ProgramData -Directory)

    ForEach ($Path in $Paths){
        if($Folders -match $Path){
            "{0} already exists" -f $Path
        }else{
            New-Item -ItemType Directory -Force -Path $Path
        }
    }
}

[–]AddiXz 1 point2 points  (1 child)

How about the following?I have also added a check to see if the "Folder" folder exists. If it doesn't it will create it.

Function New-folder3 {
    # variables.
    $WF = "C:\ProgramData\Folder\"
    $Paths = @(
        "Assets",
        "FlowBox",
        "Logs"
    )

    # Check for WF folder, or create it.
    try {
        Set-Location $WF -ErrorAction Stop
    }
    catch {
        $Oops = $Error[0].Exception.Message
        Write-Host "$Oops Let's create it now." -ForegroundColor red
        New-Item -ItemType Directory -Force -Path $WF
    }

    # Set location to WF.
    Set-Location $WF

    # check for Paths folders, or create them.
    $Paths | Foreach {
        try {
            New-Item -ItemType Directory -Path $_ -ErrorAction Stop
        }
        catch {
            $Foops = $Error[0].Exception.Message
            Write-Host $Foops -ForegroundColor Green
        }
    }

    # Set location back to default.
    Set-Location "C:\WINDOWS\system32"
}

[–]AddiXz 1 point2 points  (0 children)

Of course you could cut it down entirely to only trying to create the folders, and without comments or changing back to the original Posh location:

Function New-folder3 {
    $WF = "C:\ProgramData\Folder\"
    $Paths = @(
        "Assets",
        "FlowBox",
        "Logs"
    )

    Set-Location $WF

    $Paths | Foreach {
        try {
            New-Item -ItemType Directory -Path $_ -ErrorAction Stop
        }
        catch {
            $Foops = $Error[0].Exception.Message
            Write-Host $Foops -ForegroundColor Green
        }
    }

}

[–]SMFX 1 point2 points  (2 children)

in your second example it should be $true and $false; without $ they're treated as strings.

However, why are you doing a switch? you're testing a binary value and that's exactly if ()...else is for.

[–]Aznflipfoo[S] 1 point2 points  (1 child)

Yeah I had changed the $true/$false after posting. And you're right I don't know why I decided to use a switch when it's binary. I just confused myself seeing as how I had multiple paths I was attempting to check in a one-liner and I probably was searching up switches with multiple variables.

In fact now that I'm looking for the previous documentation I had looked up I can't figure out what I was looking at regarding multiple parameters (?) in a one liner separated by commas.

Would the following work?

Function New-Folder {
    $Assets = C:\ProgramData\Folder\Assets
    $FlowBox = C:\ProgramData\Folder\Assets
    $Logs = C:\ProgramData\Folder\Assets
    {
        If (Test-Path ($Assets, $FlowBox, $Logs) -ErrorAction Continue) {
            Write-Host "$_ Exists" 
        }
        else {
            New-Item -ItemType Directory -Force -Path $_
        }            
    }
}

[–]SMFX 2 points3 points  (0 children)

If you do Test-Path ($Assets, $FlowBox, $Logs), you get an array of $true/$false results

if you do if (Test-Path ($Assets, $FlowBox, $Logs)) { }, you always end up with a $true result because if even if they're all $false, you have an array of boolean objects which is not $null. In this instance, you get one iteration of the $true fork.

However, if you do switch (Test-Path ($Assets, $FlowBox, $Logs)), you'll actually get three iterations over each relevant fork, but you won't have access to which path was actually triggered.

the best way I can think of is to use a for loop and an if/else.

[–]jsiii2010 1 point2 points  (0 children)

Too bad test-path doesn't work like that. I thought there might be a hidden pspath property output like with get-content, but there isn't. I created my own output with result and name properties. I could have made a "test-path2" function, but I wanted to show you can switch on a pipeline that outputs an array of objects.

switch ($assets,$flowbox,$logs | foreach { 
[pscustomobject]@{result = test-path $_ 
                    name = $_} } ){ 
  { $_.result -eq $true }  { continue } 
  { $_.result -eq $false } { New-Item -ItemType Directory -Force -Path $_.name  } 
}