2017-07-25 38 views
1

我的目標是完全比較兩個目錄 - 包括目錄和子目錄的結構。完全比較目錄 - 包括移動的文件

我需要這個,因爲我想監視文件夾E:\path2中的某些內容是否發生了變化。對於這種情況,完整文件夾的副本位於C:\path1。如果有人改變了一些東西,必須在兩個目錄中完成。

這對我們很重要,因爲如果目錄中的內容發生了變化(意外或不是),它可能會破壞我們基礎架構中的其他功能。

這是我已經寫腳本:

# Compare files for "copy default folder" 
# This Script compares the files and folders which are synced to every client. 
# Source: https://mcpmag.com/articles/2016/04/14/contents-of-two-folders-with-powershell.aspx 

# 1. Compare content and Name of every file recursively 
$SourceDocsHash = Get-ChildItem -recurse –Path C:\path1 | foreach {Get-FileHash –Path $_.FullName} 
$DestDocsHash = Get-ChildItem -recurse –Path E:\path2 | foreach {Get-FileHash –Path $_.FullName} 
$ResultDocsHash = (Compare-Object -ReferenceObject $SourceDocsHash -DifferenceObject $DestDocsHash -Property hash -PassThru).Path 

# 2. Compare name of every folder recursively 
$SourceFolders = Get-ChildItem -recurse –Path C:\path1 #| where {!$_.PSIsContainer} 
$DestFolders = Get-ChildItem -recurse –Path E:\path2 #| where {!$_.PSIsContainer} 

$CompareFolders = Compare-Object -ReferenceObject $SourceFolders -DifferenceObject $DestFolders -PassThru -Property Name 
$ResultFolders = $CompareFolders | Select-Object FullName 

# 3. Check if UNC-Path is reachable 
# Source: https://stackoverflow.com/questions/8095638/how-do-i-negate-a-condition-in-powershell 
# Printout, if UNC-Path is not available. 
if(-Not (Test-Path \\bb-srv-025.ftscu.be\DIP$\Settings\ftsCube\default-folder-on-client\00_ftsCube)){ 
    $UNCpathReachable = "UNC-Path not reachable and maybe" 
} 

# 4. Count files for statistics 
# Source: https://stackoverflow.com/questions/14714284/count-items-in-a-folder-with-powershell 
$count = (Get-ChildItem -recurse –Path E:\path2 | Measure-Object).Count; 

# FINAL: Print out result for check_mk 
if($ResultDocsHash -Or $ResultFolders -Or $UNCpathReachable){ 
    echo "2 copy-default-folders-C-00_ftsCube files-and-folders-count=$count CRITIAL - $UNCpathReachable the following files or folders has been changed: $ResultDocs $ResultFolders (none if empty after ':')" 
} 
else{ 
    echo "0 copy-default-folders-C-00_ftsCube files-and-folders-count=$count OK - no files has changed" 
} 

我知道這個輸出是不完美的格式化,但它的確定。 :-)

該腳本斑點以下更改成功:

  • 創建新的文件夾或新文件
  • 重命名文件夾或文件 - >它顯示爲錯誤,但輸出是空的。我可以忍受這一點。但也許有人看到原因。 :-)
  • 刪除文件夾或文件
  • 更改文件內容

這個腳本不發現以下變化:

  • 移動文件夾或文件到其他子文件夾 。劇本仍然說「一切正常」

我一直在嘗試很多東西,但無法解決這個問題。

有沒有人可以幫助我如何擴展腳本來發現移動的文件夾或文件?

+0

而不是在事後追逐更改,您會考慮製作一個必須用於將文件放入目錄的腳本?文件提交腳本會將文件的副本放到兩個目錄中。用戶可以讀取目錄的訪問權限,但腳本會使用允許寫入目錄的憑據。或者,可能有一個單獨的提交目錄,用戶可以放置新的/更改的文件。腳本可以觀察目錄或定期將提交目錄文件複製到其他目錄。 – lit

+0

使用.NET FileSystemWatcher類可能是更好的選擇。 [從TechNet圖庫](https://gallery.technet.microsoft.com/scriptcenter/Powershell-FileSystemWatche-dfd7084b)。 –

+0

@ MikeSherrill'CatRecall':這很有趣。我會嘗試併發布反饋。 也許我必須澄清一下我的目標:我想查看文件和文件夾是否在特定目錄中更改。 (E:\ path2)我的方法是將它與參考目錄進行比較。 (C:\ path1)對不起,複雜。 –

回答

0

所以基本上你想兩個文件夾同步,並注意上所做的所有修改:

我會建議你使用

Sync-Folder Script

或者

FreeFile Sync

+0

感謝您的回答。我不想同步(寫)。只是比較(閱讀)。目標是輸出到check_mk以顯示差異並獲得警報。是否可以使用同步腳本,但在比較後只停止「模擬」並獲得輸出結果? –

0

我認爲你最好的選擇是使用.NET FileSystemWatcher類。實現一個使用它的高級函數並不是微不足道的,但我認爲它會爲你簡化一些事情。

我在學習這門課時使用了文章Tracking Changes to a Folder Using PowerShell。作者的代碼如下。我儘可能少地將它清理乾淨。 (該發佈平臺的代碼格式會讓我感到很傷心。)

我想你想這樣運行它。

New-FileSystemWatcher -Path E:\path2 -Recurse 

我可能是錯的。

Function New-FileSystemWatcher { 

    [cmdletbinding()] 
    Param (

    [parameter()] 
    [string]$Path, 

    [parameter()] 
    [ValidateSet('Changed', 'Created', 'Deleted', 'Renamed')] 
    [string[]]$EventName, 

    [parameter()] 
    [string]$Filter, 

    [parameter()] 
    [System.IO.NotifyFilters]$NotifyFilter, 

    [parameter()] 
    [switch]$Recurse, 

    [parameter()] 
    [scriptblock]$Action 

    ) 

    $FileSystemWatcher = New-Object System.IO.FileSystemWatcher 

    If (-NOT $PSBoundParameters.ContainsKey('Path')){ 
     $Path = $PWD 
    } 

    $FileSystemWatcher.Path = $Path 

    If ($PSBoundParameters.ContainsKey('Filter')) { 
     $FileSystemWatcher.Filter = $Filter 
    } 

    If ($PSBoundParameters.ContainsKey('NotifyFilter')) { 
     $FileSystemWatcher.NotifyFilter = $NotifyFilter 
    } 

    If ($PSBoundParameters.ContainsKey('Recurse')) { 
     $FileSystemWatcher.IncludeSubdirectories = $True 
    } 

    If (-NOT $PSBoundParameters.ContainsKey('EventName')){ 
     $EventName = 'Changed','Created','Deleted','Renamed' 
    } 

    If (-NOT $PSBoundParameters.ContainsKey('Action')){ 
     $Action = { 
      Switch ($Event.SourceEventArgs.ChangeType) { 
       'Renamed' { 
        $Object = "{0} was {1} to {2} at {3}" -f $Event.SourceArgs[-1].OldFullPath, 
        $Event.SourceEventArgs.ChangeType, 
        $Event.SourceArgs[-1].FullPath, 
        $Event.TimeGenerated 
       } 

       Default { 
        $Object = "{0} was {1} at {2}" -f $Event.SourceEventArgs.FullPath, 
        $Event.SourceEventArgs.ChangeType, 
        $Event.TimeGenerated 
       } 
      } 

      $WriteHostParams = @{ 
       ForegroundColor = 'Green' 
       BackgroundColor = 'Black' 
       Object = $Object 
      } 

      Write-Host @WriteHostParams 
     } 

    } 

    $ObjectEventParams = @{ 
     InputObject = $FileSystemWatcher 
     Action = $Action 
    } 

    ForEach ($Item in $EventName) { 
     $ObjectEventParams.EventName = $Item 
     $ObjectEventParams.SourceIdentifier = "File.$($Item)" 
     Write-Verbose "Starting watcher for Event: $($Item)" 
     $Null = Register-ObjectEvent @ObjectEventParams 
    } 

} 

我不認爲我在網上找到任何例子告訴您如何停止看文件系統。最簡單的方法是關閉PowerShell窗口。但我總是在五個PowerShell窗口中的每一個窗口中打開15個選項卡,關閉其中一個是令人討厭的。

取而代之,您可以使用Get-Job獲取註冊事件的ID。然後使用Unregister-Event -SubscriptionId n註銷該事件,其中'n'表示您在Get-Job的Id屬性中找到的數字。

+0

您也可以編寫使用文件系統監視器的Windows服務。 –