Home > Enterprise >  Powershell If statement with multiple conditions
Powershell If statement with multiple conditions

Time:05-19

I have a Powershell script with If statement and multiple conditions. My code is working great but I am looking for to display which condition my object doesn't respect.

Get-ChildItem $Path -Directory -Force | ForEach-Object {

$FolderName = $_.BaseName -match $Folderpattern
$DateOK = $_.LastWriteTime -lt (Get-Date).AddDays(-3))
$Folder = $_.BaseName
    
if (($FolderName) -and ($DateOK) {
                write-host("$Folder can be moved") 
            }
            else {
                write-host("$Folder can't be moved")
            }
        }

I would like to display "$folder can't be moved because it doesn't match the pattern" if it doesn't respect the $FolderName condition.

And display "$folder can't be moved because the last write time is less than 3 days" if it doesn't respect the $DateOK condition.

thanks for the help

CodePudding user response:

If this is just for checking and not for keeping a log where you need those specific messages I might go for something simple where we just capture the true and false values for each of the tests.

$path = C:\temp
Get-ChildItem $Path -Directory -Force |
    ForEach-Object {
        [PSCustomObject]@{
            Folder         = $_.BaseName
            LastWriteTime  = $_.LastWriteTime
            FolderNameTest = $_.BaseName -match 'test'
            DateOKTest     = $_.LastWriteTime -lt (Get-Date).AddDays(-30)
        }
    }

Sample Output

Folder         LastWriteTime       FolderNameTest DateOKTest
------         -------------       -------------- ----------
.git           06.09.2021 01:06:06          False       True
.vscode        25.09.2021 10:06:11          False       True
1              22.09.2021 22:30:26          False       True
batch_test     02.05.2022 22:29:25           True      False
cleanup        20.09.2021 10:02:51          False       True
DeviceDatabase 26.09.2021 12:07:26          False       True
host           22.09.2021 23:23:38          False       True
move_logs      26.04.2022 19:28:59          False      False
test_run       01.03.2022 22:14:14           True       True

You can then pipe this to Export-Csv if you like

CodePudding user response:

There are various ways to go about this; but this one is clean and easy to understand, so would be my preferred route:


Function Move-FolderConditional { # todo: give this cmdlet a better name for your context
    [CmdletBinding()]
    Param (
        [Parameter(Mandatory, ValueFromPipeline)]
        [System.IO.DirectoryInfo[]]$Path
        ,
        [Parameter(Mandatory)]
        [System.IO.DirectoryInfo]$Destination
        ,
        # files matching this pattern get moved to the target
        [Parameter(Mandatory)]
        [string]$ArchivableFolderPattern
        ,
        # Files older than this date get moved to the target
        [Parameter()]
        [string]$MinKeepDateUtc = (Get-Date).AddDays(-3).ToUniversalTime()
    )
    Process {
        foreach ($directory in $Path) {
            if ($directory.BaseName -notmatch $ArchivableFolderPattern) {
                Write-Warning "Could not move folder '$($directory.FullName)' as the name does not match the required pattern"
                continue;
            }
            if ($directory.LastWriteTimeUtc -ge $MinKeepDateUtc) {
                Write-Warning "Could not archive folder '$($directory.FullName)' as it was last updated at '$($directory.LastWriteTimeUtc.ToString('u'))'"
                continue;
            }
            try {
                #Move-Item -Path $directory -Destination $Destination -ErrorAction Stop # Uncommend this if you actually want to move your files
                Write-Information "Successfully moved '$($directory.FullName)' to '$($Destination.FullName)'" 
            } catch [System.Management.Automation.ItemNotFoundException] { # For this exception we'd probably check in the Begin block instead - but this is just to give the idea that we could add a try/catch if required
                Write-Warning "Could not archive folder '$($directory.FullName)' the target directory does not exist: '$($Destination.FullName)'"
            }  
        }
    }
}

# Example usage
Get-ChildItem $path -Directory -Force | Move-FolderConditional -ArchivableFolderPattern '^log' -InformationAction Continue -Destination 'z:\archive\'

But other options are available (I've just included snippets to give the gist of these):

Switch Statement

switch ( $directory )
{
    {$_.BaseName -notmatch $ArchivableFolderPattern}
    {
        Write-Warning "Could not move folder '$($_.FullName)' as the name does not match the required pattern"
        break
    }
    {$_.LastWriteTimeUtc -ge $MinKeepDateUtc}
    {
        Write-Warning "Could not archive folder '$($_.FullName)' as it was last updated at '$($_.LastWriteTimeUtc.ToString('u'))'"
        break
    }
    default 
    {
        Write-Information "Successfully moved '$($_.FullName)' to '$($Destination.FullName)'" 
    }
}

Flags

[bool]$archiveFolder = $true
if ($directory.BaseName -notmatch $ArchivableFolderPattern) {
    Write-Warning "Could not move folder '$($directory.FullName)' as the name does not match the required pattern"
    $archiveFolder = $false
}
if ($directory.LastWriteTimeUtc -ge $MinKeepDateUtc) { 
    # note: this will process even if archivefolder is already false... you can use `else` or amend the condition to include `$archiveFolder -or ($directory.LastWriteTimeUtc -ge $MinKeepDateUtc)`; though if going that route it's better to use the switch statement.
    Write-Warning "Could not archive folder '$($directory.FullName)' as it was last updated at '$($_.LastWriteTimeUtc.ToString('u'))'"
    $archiveFolder = $false
}
if ($archiveFolder) {
    Write-Information "Successfully moved '$($directory.FullName)' to '$($Destination.FullName)'" 
}

Other

Or you can do combinations of the above (e.g. use the switch statement to set your flags (in which case you can optionally remove the break so that all issues are displayed).

  • Related