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

wvmv3b1j  于 2022-12-13  发布在  Shell
关注(0)|答案(4)|浏览(269)

我们有两个文件夹:

  • FolderA:D:\Powershell\原始版本
  • FolderB:D:\Powershell\副本

现在,我想让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中的文件。

kqlmhetl

kqlmhetl1#

我认为您应该尝试以下方法,它可以根据您的要求更改syncMode。1是单向同步源到目标,2是双向同步

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

touch $source'initial.initial'
touch $target'initial.initial'

$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
    }
    rm $source'initial.initial'
    rm $target'initial.initial'
c7rzv4ha

c7rzv4ha2#

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

dy2hfwbg

dy2hfwbg3#

这是一个完整的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 **************************"
ljsrvy3e

ljsrvy3e4#

你看过Robocopy(鲁棒的文件复制)吗?它可以与PS一起使用,并提供你所寻找的iidoEe。它是专为文件夹的可靠复制或镜像(更改/添加/删除)而设计的,只需根据需要选择选项。
Robocopy sourceFolder destinationFolder /MIR /FFT /Z /XA:H /W:5
/MIR选项镜像源目录和目标目录。如果在源目录中删除了文件,它将删除目标目录中的文件。
Robocopy

相关问题