2014-05-22 151 views
3

雖然這看起來簡單的(它可能是!)我似乎無法找到一個方法來解決它。PowerShell的 - 比較兩份文件的列表,並對其內容

我所試圖做的是通過自己的內容比較過濾的文件的兩個列表。這方面的一個例子是,如果兩個列表回來說,他們曾在該位置的東西\文件\ morefiles那麼這將這些文件放在一起比較,並輸出,其中,什麼變化是一個項目叫做file.config。本質上,對.config文件進行差異化並顯示更改的位置。這通常比較兩個文件(比較對象等可以使用)很簡單,但因爲它是兩個文件列表,而不是單個的文件列表,所以我不知所措。

我需要這樣做,以顯示在軟件升級到配置文件所需要的所有更改的列表,所以從軟件的一個版本到下一個,什麼是對配置文件所做的更改。我在powershell中這樣做是因爲它能夠輕鬆與HG mercurial進行交互,並且由經驗較少的用戶(通過bat文件)運行。

的目標是有一個.txt文件,列出所有在新安裝變化與舊的或類似的東西比較的文件。

這是我到目前爲止有:

$A = Get-ChildItem -Recurse -path "C:\repos\Dev\Projects\Bat\CurrentVersionRepoCloneTemp" -filter "*.config" 

$B = Get-ChildItem -Recurse -path "C:\repos\Dev\Projects\Bat\UpgradeVersionRepoCloneTemp" -filter "*.config" 

$C = Compare-Object $A $B -Property ('Name', 'Length') -PassThru | Where-Object {$_.FullName -eq $_.FullName} | ForEach-Object 
{  
    Compare-Object (Get-Content FileA)(Get-Content FileB) #I know this doesn't work 
}$C 

思路或解決方案?

謝謝大家提前

回答

3

你可以做一個checksum of each file和比較,...

$md5 = new-object -TypeName System.Security.Cryptography.MD5CryptoServiceProvider 
$hash = [System.BitConverter]::ToString($md5.ComputeHash([System.IO.File]::ReadAllBytes($file))) 
2

添Ferrill的檢查更新的文件的想法似乎是一個更好的方法來比較的文件。做類似

$A = Get-ChildItem -Recurse -path "C:\repos\Dev\Projects\Bat\CurrentVersionRepoCloneTemp" -filter "*.config" 
$B = Get-ChildItem -Recurse -path "C:\repos\Dev\Projects\Bat\UpgradeVersionRepoCloneTemp" -filter "*.config" 
$A | %{$_ | Add-Member "MD5" ([System.BitConverter]::ToString($md5.ComputeHash([System.IO.File]::ReadAllBytes($_))))} 
$B | %{$_ | Add-Member "MD5" ([System.BitConverter]::ToString($md5.ComputeHash([System.IO.File]::ReadAllBytes($_))))} 

然後,我會做比較和按目錄分組。

$C = Compare-Object $A $B -Property ('Name', 'MD5') - Passthrough | Group Directory 

之後,得到實際的變化,這會有點慢。對文件內容進行逐行匹配很粗糙,但如果它們不是太大,它應該仍然在一瞬間發生。我會建議這樣的:

$Output = @() 
ForEach($File in $C[1].Group){ 
    $OldData = GC $File 
    $C[0].Group | ?{$_.Name -eq $File.Name} | %{ 
     $NewData = GC $_ 
     $UpdatedLines = $NewData | ?{$OldData -inotcontains $_} 
     $OldLines = $OldData | ?{$NewData -inotcontains $_} 
     $Output += New-Object PSObject -Property @{ 
      UpdatedFile=$_.FullName 
      OriginalFile=$File.FullName 
      Changes=$UpdatedLines 
      Removed=$OldLines 
     } 
    } 
} 

一旦你有,你只需要輸出它的東西可讀。也許是這樣的:

Get-Date | Out-File "C:\repos\Dev\Projects\Bat\UpgradeVersionRepoCloneTemp\ChangeLog.txt" 
$Output|%{$_|FT OriginalFile,UpdatedFile; "New/Changed Lines"; "-----------------"; $_.Changes; " "; "Old/Removed Lines"; "-----------------"; $_.Removed} | Out-File "C:\repos\Dev\Projects\Bat\UpgradeVersionRepoCloneTemp\ChangeLog.txt" -Append