Назад | Перейти на главную страницу

Как сравнить две папки в PowerShell 5.1?

Мне очень сложно понять, что PS пытается мне сказать. Я создал сценарий, предназначенный для сравнения файлов в двух каталогах. Я хочу вывести любые различия в имени, количестве файлов или длине в любом каталоге. В конце концов, я бы хотел, чтобы он ошибался, если есть различия. Вот что у меня есть:

Write-host "$(Get-Date) - Comparing $deploy_src\bin $deploy_dst\bin"
$bin_src = Get-ChildItem $deploy_src
$bin_dst = Get-ChildItem $deploy_dst

if (Compare-Object $bin_src.Name $bin_dst.Name) {
   # throw "Directories differ"
}

И вот (менее чем полезный) результат, который я вижу:

02/24/2020 09:57:36 - Comparing J:\AdvantageProxy\Development\bin J:\AdvantageProxy\Deploy-QA-2020-02-21\bin
02/24/2020 09:57:36 - done.
Name Length SideIndicator
---- ------ -------------
         38 =>           
         20 <= 

Обновление: файлы находятся в общей папке FSx, доступной для Mac. Это то, что выводится для diff, который показывает только .DS_Store в каталоге, доступ к которому осуществляется напрямую с Mac:

 $ rsync -n -a -i --delete /Volumes/share/AdvantageProxy/Development/bin/. /Volumes/share/AdvantageProxy/Deploy-QA-2020-02-21/bin/.
 *deleting   .DS_Store
 .d..t....... ./
 .d..t....... de/
 .d..t....... es/
 .d..t....... ja/
 .d..t....... ru/

(Я использовал rsync, чтобы не тратить время на сравнение содержимого файлов. ... Это показывает, что в $ deploy_dst \ bin есть файл, которого нет в $ deploy_src \ bin, и отметки времени на несколько папок отличается. Я ожидаю увидеть нечто подобное с решением Powershell.)

Также обратите внимание - я стараюсь по возможности избегать установки дополнительных зависимостей, поэтому я пытаюсь сделать это через PS.

В итоге я создал собственное решение. Соответствующие его части выглядят так:

      function Compare_Directory
      {
          [CmdletBinding()]
          Param(
               [string]
              [Parameter(Mandatory=$true)]
              $src_dir,
              [Parameter(Mandatory=$true)]
              [string]
              $dest_dir
          )

          Write-Host "$(Get-Date) - Diffing files in $src_dir to $dest_dir (will only report differences)"

          # Get .FullName to avoid issues with string replace not matching FullName to non-full file names (ie, paths using PSdrives)
          $src_str = (Get-Item $src_dir).FullName
          $dest_str = (Get-Item $dest_dir).FullName

          if ($verbose>1){
            Write-Host "$(Get-Date) - $src_str -> $dest_str"
          }

          # Get all files under $folder1, filter out directories
          $src_files = Get-ChildItem  $src_dir -force | Where-Object { -not $_.PsIsContainer }  # -Recurse
          # -force will pick up dotfiles (or windowspeak, files with the hidden attribute set)

          $i=0
          $mismatches=0
          $src_files | ForEach-Object {

                  $src_fl = (Get-Item $_.FullName -force)
                  $dest_flnm = $_.FullName.replace($src_str, $dest_str)
                  $dest_fl = (Get-Item $dest_flnm -force)

                  # Currently, this will cause an error if a file exists in src directory but not dest directory
                  # I don't know how to write this so that it can error more than once depending on verbosity 
                  #   like the rest of the script and it's not a priority for me.

                  if ($verbose>1){
                    Write-Host "$src_fl ?? $dest_fl"
                  }

                  If ( Compare-Object $src_fl $dest_fl -Property Name, Length ) {

                      # List files not matching
                      Write-Host "src- $src_fl"
                      Write-Host "dest- $dest_fl"

                      # if verbosity <0, fail fast, otherwise provide maximum insight (logging)
                      if ($verbose -lt 0){
                        throw "Verbosity set to intolerant; First mismatch found- $src_fl"
                      }
                      else{
                        $mismatches+=1
                      }

                  }
          }
          Write-Host "$i files compared"
          if ($mismatches -gt 0){
            throw "Mismatching files found: $mismatches"
          }
      }

      # Diff directories in both directions to identify differences in file names

      Write-host "$(Get-Date) - Comparing $backup_src and $deploy_dst (->)"
      Compare_Directory $backup_src $deploy_dst
      Write-host "$(Get-Date) - Comparing $backup_src and $deploy_dst (<-)"
      Compare_Directory $deploy_dst $backup_src

      Write-host "$(Get-Date) - Comparing $deploy_src\bin $deploy_dst\bin (->)"
      Compare_Directory $deploy_src\bin $deploy_dst\bin
      Write-host "$(Get-Date) - Comparing $deploy_src\bin $deploy_dst\bin (->)"
      Compare_Directory $deploy_dst\bin $deploy_src\bin