用于比较两个应该相同但位于不同服务器上的目录(包括子目录和内容)的PowerShell脚本

brvekthn  于 2022-11-10  发布在  Shell
关注(0)|答案(1)|浏览(122)

我想运行一个PowerShell脚本,它可以由用户提供目录名,然后它将检查目录、子目录和这些目录的所有文件内容,以比较它们是否彼此相同。有8台服务器应该都有相同的文件和内容。下面的代码似乎没有执行我想要的操作。我已经看到了Compare-Object、Get-ChildItem和Get-FileHash的使用,但还没有找到正确的组合,我确信它们实际上正在完成任务。如有任何帮助,我们将不胜感激!

$35 = "\\server1\"
$36 = "\\server2\"
$37 = "\\server3\"
$38 = "\\server4\"
$45 = "\\server5\"
$46 = "\\server6\"
$47 = "\\server7\"
$48 = "\\server8\"
do{
Write-Host "|1 : New   |"
Write-Host "|2 : Repeat|"
Write-Host "|3 : Exit  |"
$choice = Read-Host -Prompt "Please make a selection"
    switch ($choice){
        1{
            $App = Read-Host -Prompt "Input Directory Application"
        }
        2{
            #rerun
        }
    3{
        exit;       }
    }

$c35 = $35 + "$App" +"\*"
$c36 = $36 + "$App" +"\*"
$c37 = $37 + "$App" +"\*"
$c38 = $38 + "$App" +"\*"
$c45 = $45 + "$App" +"\*"
$c46 = $46 + "$App" +"\*"
$c47 = $47 + "$App" +"\*"
$c48 = $48 + "$App" +"\*"

Write-Host "Comparing Server1 -> Server2"
if((Get-ChildItem $c35 -Recurse | Get-FileHash | Select-Object Hash,Path).hash -eq (Get-ChildItem $c36 -Recurse | Get-FileHash | Select-Object Hash,Path).hash){"Identical"}else{"NOT Identical"}

Write-Host "Comparing Server1 -> Server3"
if((Get-ChildItem $c35 -Recurse | Get-FileHash | Select-Object Hash,Path).hash -eq (Get-ChildItem $c37 -Recurse | Get-FileHash | Select-Object Hash,Path).hash){"Identical"}else{"NOT Identical"}

Write-Host "Comparing Server1 -> Server4"
if((Get-ChildItem $c35 -Recurse | Get-FileHash | Select-Object Hash,Path).hash -eq (Get-ChildItem $c38 -Recurse | Get-FileHash | Select-Object Hash,Path).hash){"Identical"}else{"NOT Identical"}

Write-Host "Comparing Server1 -> Server5"
if((Get-ChildItem $c35 -Recurse | Get-FileHash | Select-Object Hash,Path).hash -eq (Get-ChildItem $c45 -Recurse | Get-FileHash | Select-Object Hash,Path).hash){"Identical"}else{"NOT Identical"}

Write-Host "Comparing Server1 -> Server6"
if((Get-ChildItem $c35 -Recurse | Get-FileHash | Select-Object Hash,Path).hash -eq (Get-ChildItem $c46 -Recurse | Get-FileHash | Select-Object Hash,Path).hash){"Identical"}else{"NOT Identical"}

Write-Host "Comparing Server1 -> Server7"
if((Get-ChildItem $c35 -Recurse | Get-FileHash | Select-Object Hash,Path).hash -eq (Get-ChildItem $c47 -Recurse | Get-FileHash | Select-Object Hash,Path).hash){"Identical"}else{"NOT Identical"}

Write-Host "Comparing Server1 -> Server8"
if((Get-ChildItem $c35 -Recurse | Get-FileHash | Select-Object Hash,Path).hash -eq (Get-ChildItem $c48 -Recurse | Get-FileHash | Select-Object Hash,Path).hash){"Identical"}else{"NOT Identical"}

} until ($choice -eq 3)
unftdfkk

unftdfkk1#

下面是一个示例函数,它试图有效地比较一个Reference目录和多个Difference目录。它通过首先比较最容易获得的信息和在第一个差异处停止来做到这一点。

  • 一次获取Reference目录中文件的所有相关信息,包括散列(不过只有在必要时才获取散列可以更优化)。
  • 对于每个不同目录,请按以下顺序进行比较:
  • 文件数**-如果不同,那么显然目录也不同
  • 相对文件路径**--如果在Reference目录中找不到Difference目录的所有路径,则目录是不同的
  • 文件大小**-应该显而易见
  • 文件散列**-仅当文件大小相等时才需要计算散列
Function Compare-MultipleDirectories {
    param(
        [Parameter(Mandatory)] [string] $ReferencePath,
        [Parameter(Mandatory)] [string[]] $DifferencePath
    )

    # Get basic file information recursively by calling Get-ChildItem with the addition of the relative file path
    Function Get-ChildItemRelative {
        param( [Parameter(Mandatory)] [string] $Path )

        Push-Location $Path  # Base path for Get-ChildItem and Resolve-Path
        try { 
            Get-ChildItem -File -Recurse | Select-Object FullName, Length, @{ n = 'RelativePath'; e = { Resolve-Path $_.FullName -Relative } }
        } finally { 
            Pop-Location 
        }
    }

    Write-Verbose "Reading reference directory '$ReferencePath'"

    # Create hashtable with all infos of reference directory
    $refFiles = Get-ChildItemRelative $ReferencePath |
        Select-Object *, @{ n = 'Hash'; e = { (Get-FileHash $_.FullName -Algorithm MD5).Hash } } | 
        Group-Object RelativePath -AsHashTable 

    # Compare content of each directory of $DifferencePath with $ReferencePath
    foreach( $diffPath in $DifferencePath ) {
        Write-Verbose "Comparing directory '$diffPath' with '$ReferencePath'"

        $areDirectoriesEqual = $false
        $differenceType = ''

        $diffFiles = Get-ChildItemRelative $diffPath

        # Directories must have same number of files
        if( $diffFiles.Count -eq $refFiles.Count ) {

            # Find first different path (if any)
            $firstDifferentPath = $diffFiles | Where-Object { -not $refFiles.ContainsKey( $_.RelativePath ) } | 
                                  Select-Object -First 1

            if( -not $firstDifferentPath ) {

                # Find first different content (if any) by file size comparison
                $firstDifferentFileSize = $diffFiles |
                    Where-Object { $refFiles[ $_.RelativePath ].Length -ne $_.Length } |
                    Select-Object -First 1

                if( -not $firstDifferentFileSize ) {

                    # Find first different content (if any) by hash comparison
                    $firstDifferentContent = $diffFiles | 
                        Where-Object { $refFiles[ $_.RelativePath ].Hash -ne (Get-FileHash $_.FullName -Algorithm MD5).Hash } | 
                        Select-Object -First 1

                    if( -not $firstDifferentContent ) {
                        $areDirectoriesEqual = $true
                    }
                    else {
                        $differenceType = 'Content'
                    } 
                }
                else {
                    $differenceType = 'FileSize'
                }
            }
            else {
                $differenceType = 'Path'
            }
        }
        else {
            $differenceType = 'FileCount'
        }

        # Output comparison result
        [PSCustomObject]@{ 
            ReferencePath = $ReferencePath  
            DifferencePath = $diffPath  
            Equal = $areDirectoriesEqual  
            DiffCause = $differenceType 
        }
    }
}

使用示例:


# compare each of directories B, C, D, E, F against A

Compare-MultipleDirectories -ReferencePath 'A' -DifferencePath 'B', 'C', 'D', 'E', 'F' -Verbose

输出示例:

ReferencePath DifferencePath Equal DiffCause
------------- -------------- ----- ---------
A             B               True 
A             C              False FileCount
A             D              False Path     
A             E              False FileSize 
A             F              False Content

DiffCause列提供了该函数认为目录不同的原因。

注:

  • Select-Object -First 1是一个巧妙的技巧,可以在我们得到第一个结果后停止搜索。它之所以高效,是因为它不会首先处理所有输入并丢弃除第一个项目之外的所有内容,而是在找到第一个项目后取消管道。
  • Group-Object RelativePath -AsHashTable创建文件信息的hashtable,以便可以通过RelativePath属性快速查找。
  • 空的子目录被忽略**,因为函数只看文件。例如,如果引用路径包含一些空目录,但差异路径不包含,并且所有其他目录中的文件是相等的,则该函数将这些目录视为平等。
  • 我选择了MD5算法,因为它比Get-FileHash使用的默认SHA-256算法更快,但它不安全。有人可以很容易地操纵一个不同的文件,使其具有与原始文件相同的MD5哈希。不过,在一个受信任的环境中,这并不重要。如果需要更安全的比较,请移除-Algorithm MD5

相关问题