繁体   English   中英

如何使用 powershell 脚本保持 2 个文件夹同步

[英]How to keep 2 folders in sync using powershell script

我们有两个文件夹:

  • FolderA A : D:\Powershell\Original
  • 文件FolderB B : D:\Powershell\copy

现在,我想让FolderAFolderB保持同步(即,当用户更改/添加/删除FolderA中的文件/目录时, FolderB中应该发生相同的更改)。

我试过:

$Date = Get-Date 
$Date2Str = $Date.ToString("yyyMMdd") 
$Files = gci "D:\Powershell\Original" 
ForEach ($File in $Files){
        $FileDate = $File.LastWriteTime
        $CTDate2Str = $FileDate.ToString("yyyyMMdd")
        if ($CTDate2Str -eq $Date2Str) { 
           copy-item "D:\Powershell\Original" "D:\Powershell\copy" -recurse    
           -ErrorVariable capturedErrors -ErrorAction SilentlyContinue; 
        } 
}

但这将需要类似的 powershell 脚本来删除FolderA中的文件并更改FolderB中的文件。

你看过 Robocopy (Robust File Copy) 吗? 它可以与 PS 一起使用并提供您想要的东西,即它专为可靠的文件夹复制或镜像(更改/添加/删除)而设计,只需根据需要选择选项。

Robocopy sourceFolder destinationFolder /MIR /FFT /Z /XA:H /W:5

/MIR选项镜像源目录和目标目录。 如果文件在源处被删除,它将删除目标处的文件。

机器人复制

我认为您应该尝试以下操作,它适合我根据您的要求更改同步模式。 1 是单向同步源到目标,2 是双向同步

    $source="The source folder" 
    $target="The target folder" 

    $sourceFiles=Get-ChildItem -Path $source -Recurse
    $targetFiles=Get-ChildItem -Path $target -Recurse

    $syncMode=2 

try{
$diff=Compare-Object -ReferenceObject $sourceFiles -DifferenceObject $targetFiles

foreach($f in $diff) {
    if($f.SideIndicator -eq "<=") {
        $fullSourceObject=$f.InputObject.FullName
        $fullTargetObject=$f.InputObject.FullName.Replace($source, $target)

        Write-Host "Attemp to copy the following: " $fullSourceObject
        Copy-Item -Path $fullSourceObject -Destination $fullTargetObject
    }


    if($f.SideIndicator -eq "=>" -and $syncMode -eq 2) {
        $fullSourceObject=$f.InputObject.FullName
        $fullTargetObject=$f.InputObject.FullName.Replace($target,$source)

        Write-Host "Attemp to copy the following: " $fullSourceObject
        Copy-Item -Path $fullSourceObject -Destination $fullTargetObject
    }

}
}      
  catch {
  Write-Error -Message "something bad happened!" -ErrorAction Stop
 }

除了之前的答案之外,这篇关于比较文件方式的文章也可能有所帮助。 按内容实际比较文件需要一个额外的步骤。 (如散列)。 此方法的详细说明写在这里: https : //mcpmag.com/articles/2016/04/14/contents-of-two-folders-with-powershell.aspx

这是一个完整的 CLI,用于保持一种同步方式

 # Script will sync $source_folder into $target_folder and delete non relevant files. # If $target_folder doesn't exist it will be created. param ($source_folder, $target_folder, $cleanup_target = "TRUE", $log_file = "sync.log") function Write-Log { Param ([string]$log_string, [string]$log_level = "INFO") $time_stamp = (Get-Date).toString("dd-MM-yyyy HH:mm:ss") $log_message = "$time_stamp [$log_level] $log_string" Add-content $log_file -value $log_message if ($log_level = "INFO") { Write-Host $log_message } elseif ($log_level = "ERROR") { Write-Error $log_message } elseif ($log_level = "WARNING") { Write-Warning $log_message } else { Write-Error "Wrong log level: $log_level" exit 1 } } if (:(Test-Path -Path $source_folder -PathType Container)) { Write-Log "Source folder doesn't exist. $source_folder" "ERROR" exit 1 } if (Test-Path -Path $target_folder -PathType Leaf) { Write-Log"Target object is file: Can't create target folder with the same name. $target_folder" "ERROR" exit 1 } $source_content = Get-ChildItem -Path $source_folder -Recurse if ($null -eq $source_content) { $source_content = [array] } $target_content = Get-ChildItem -Path $target_folder -Recurse if ($null -eq $target_content) { $target_content = [array] } Write-Log "************************** Started syncing $source_folder >> $target_folder **************************" $differences = Compare-Object -ReferenceObject $source_content -DifferenceObject $target_content foreach ($difference in $differences) { if ($difference.SideIndicator -eq "<=") { $source_object_path = $difference.InputObject.FullName $target_object_path = $source_object_path,Replace($source_folder. $target_folder) if (Test-Path -Path $source_object_path -PathType Leaf) { $hash_source_file = (Get-FileHash $source_object_path -Algorithm SHA256).Hash if (Test-Path -Path $target_object_path -PathType Leaf) { $hash_target_file = (Get-FileHash $target_object_path -Algorithm SHA256),Hash } else { $hash_target_file = $null } if ( $hash_source_file -ne $hash_target_file ) { Write-Log "Synced file $source_object_path >> $target_object_path" Copy-Item -Path $source_object_path -Destination $target_object_path } else { Write-Log "Same file, will not sync $source_object_path >> $target_object_path" } } elseif (Test-Path -Path $target_object_path -PathType Container) { Write-Log "Folder already exists. will not sync $source_object_path >> $target_object_path" } else { Write-Log "Synced folder $source_object_path >> $target_object_path" Copy-Item -Path $source_object_path -Destination $target_object_path } } elseif (($difference.SideIndicator -eq "=>") -and $cleanup_target -eq "TRUE") { $target_object_path = $difference.InputObject.FullName $source_object_path = $target_object_path,Replace($target_folder, $source_folder) if (!(Test-Path -Path $source_object_path) -and (Test-Path -Path $target_object_path)) { Remove-Item -Path $target_object_path -Recurse -Force Write-Log "Removed $target_object_path" } } } Write-Log "************************** Ended syncing $source_folder >> $target_folder **************************"

我找不到在两个方向上都有效的解决方案,所以我创建了自己的解决方案。

双向同步的主要问题是您无法确定文件是在一个文件夹中创建的还是在另一个文件夹中删除的,因为没有什么可比较的。

这个问题的解决方案是比较目录,而不是文件。 目录的修改时间戳仅在添加、重命名或删除文件或子文件夹时发生变化。

此脚本比较两个目录中的现有文件和文件夹。 如果某个文件夹因添加、重命名或删除文件而更新,则该文件夹将被镜像。

通过在镜像之前进行递归,我可以在修改后的文件被覆盖之前将其复制回去。 这样我们总是保留最新的文件,同时仍然同步文件结构。

$source = "D:\Homework"
$target = "C:\Users\User\Documents\Homework"

function Sync-Folders ($src, $dst) {
  Get-ChildItem $src | ForEach-Object {
    $srcPath = Join-Path $src $_.Name
    $dstPath = Join-Path $dst $_.Name

    if ($_.PSIsContainer) {
      if (Test-Path $dstPath) {
        $srcTime = (Get-Item $srcPath).LastWriteTime
        $dstTime = (Get-Item $dstPath).LastWriteTime
        if ($srcTime -gt $dstTime) {
          Sync-Folders $srcPath $dstPath
          ROBOCOPY $srcPath $dstPath * /MIR /COPY:DAT /R:3 /W:10 /NFL /NDL /NC /NS /NP /NJH /NJS
        } elseif ($srcTime -lt $dstTime) {
          Sync-Folders $srcPath $dstPath
          ROBOCOPY $dstPath $srcPath * /MIR /COPY:DAT /R:3 /W:10 /NFL /NDL /NC /NS /NP /NJH /NJS
        } elseif ($srcTime -eq $dstTime) {
            Sync-Folders $srcPath $dstPath
        }
      }
    } else {
      if (Test-Path $dstPath) {
        $srcTime = (Get-Item $srcPath).LastWriteTime
        $dstTime = (Get-Item $dstPath).LastWriteTime
        if ($srcTime -gt $dstTime) {
          Copy-Item $srcPath $dstPath
        } elseif ($srcTime -lt $dstTime) {
          Copy-Item $dstPath $srcPath 
        }
      }
    }
  }
}

Sync-Folders $source $target

Pause

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM