파워셸 스크립트를 사용하여 두 폴더를 동기화하는 방법
두 개의 폴더가 있습니다.
FolderA
D:\Powershell\원본FolderB
D:\Powershell\copy
이제, 저는 계속하고 싶습니다.FolderA
그리고.FolderB
동기화(즉, 사용자가 파일/디렉토리를 변경/수정/수정할 때)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;
}
}
그러나 이를 위해서는 파일을 삭제하기 위해 유사한 파워셸 스크립트가 필요합니다.FolderA
의 변화FolderB
.
로보카피(Robocopy, 강력한 파일 복사)를 살펴보셨습니까?PS와 함께 사용할 수 있으며 원하는 것을 제공합니다. 즉, 폴더의 안정적인 복사 또는 미러링(변경/추가/제거)을 위해 설계되었습니다. 필요에 따라 옵션을 선택하기만 하면 됩니다.
Robocopy sourceFolder destinationFolder /MIR /FFT /Z /XA:H /W:5
그/MIR
옵션은 원본 디렉터리와 대상 디렉터리를 미러링합니다.원본에서 파일이 삭제된 경우 대상에 있는 파일이 삭제됩니다.
다음을 시도해보셔야 할 것 같습니다. 요구 사항에 따라 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'
이전 답변 외에도 파일을 비교하는 방법에 대한 이 기사는 도움이 될 수 있습니다. 실제로 파일을 내용별로 비교하려면 추가 단계가 필요합니다.(해싱처럼)이 방법에 대한 자세한 설명은 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
언급URL : https://stackoverflow.com/questions/25869806/how-to-keep-2-folders-in-sync-using-powershell-script
'source' 카테고리의 다른 글
Spring Boot connect Mysql과 MongoDb (0) | 2023.08.22 |
---|---|
PowerShell을 사용한 종속성 주입 (0) | 2023.08.22 |
MariaDB: 대량 삽입 작업을 활성화하는 방법 (0) | 2023.08.22 |
라디오 단추의 원 색 변경 (0) | 2023.08.22 |
Ubuntu에서 기본 데이터 디렉토리 MariaDB를 변경한 후 테스트 파일을 생성할 수 없음 (0) | 2023.08.22 |