具有多个条件的 Powershell If 语句

Powershell If statement with multiple conditions

我有一个带有 If 语句和多个条件的 Powershell 脚本。我的代码运行良好,但我希望显示我的对象不符合的条件。

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")
            }
        }

如果不符合 $FolderName 条件,我想显示“$folder can't be moved because it doesn't match the pattern”。

如果不满足$DateOK 条件,则显示“$folder can't be moved because the last write time is less than 3 days”。

感谢帮助

有多种方法可以解决这个问题;但是这个很干净,也很容易理解,所以是我的首选路线:


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\'

但是还有其他选项可用(我只是包含了一些片段来说明这些要点):

切换语句

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)'" 
    }
}

旗帜

[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)'" 
}

其他

或者您可以组合使用上述方法(例如,使用 switch 语句设置标志(在这种情况下,您可以选择删除 break 以便显示所有问题)。

如果这只是为了检查而不是为了在您需要那些特定消息的地方保留日志,我可能会选择一些简单的方法,我们只捕获每个测试的真值和假值。

$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)
        }
    }

示例输出

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

如果您愿意,您可以将其通过管道传输到 Export-Csv