2017-07-25 40 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服务。 –