Powershell Copy-Item이지만 변경된 파일만 복사
디렉토리를 통해 반복해서 A에서 B로 복사하려고 합니다.이 작업은 다음과 같이 수행할 수 있습니다.
Copy-Item C:\MyTest C:\MyTest2 –recurse
새 파일(src에 존재하지만 dest가 아닌 파일)만 복사하고 날짜 시간 스탬프가 아닌 CRC 검사에 따라 변경되었을 수 있는 파일만 복사할 수 있기를 원합니다.
$file = "c:\scripts"
param
(
$file
)
$algo = [System.Security.Cryptography.HashAlgorithm]::Create("MD5")
$stream = New-Object System.IO.FileStream($file, [System.IO.FileMode]::Open)
$md5StringBuilder = New-Object System.Text.StringBuilder
$algo.ComputeHash($stream) | `
% { [void] $md5StringBuilder.Append($_.ToString("x2")) }
$md5StringBuilder.ToString()
$stream.Dispose()
이 코드는 특정 파일에 대한 CRC 검사를...저는 제가 정말로 필요한 것을 주기 위해 두 대본을 어떻게 조합해야 할지 잘 모르겠습니다.위의 CRC 체크가 실제로 정확한 방법인지에 대해서도 잘 모르겠습니다.
통찰력 있는 사람?
이 두 가지 모두 파워셸에 대한 확실한 해답이지만, 로보카피(MS 제공 강력한 복사본 애플리케이션)를 활용하는 것이 훨씬 더 쉬울 것입니다.
robocopy "C:\SourceDir\" "C:\DestDir\" /MIR
같은 일을 해낼 겁니다
스크립트를 보다 안정적으로 유지 관리할 수 있는 몇 가지 지침이 있습니다.
원본 스크립트를 필터로 변환합니다.
filter HasChanged {
param($file)
# if $file's MD5 has does not exist
# then return $_
}
그런 다음 업데이트된 모든 파일을 필터링하고 복사하기만 하면 됩니다.
# Note that "Copy-Item" here does not preserve original directory structure
# Every updated file gets copied right under "C:\MyTest2"
ls C:\MyTest -Recurse | HasChanged | Copy-Item -Path {$_} C:\MyTest2
아니면 서브디렉토리를 생성하는 다른 함수를 만들 수도 있습니다.
ls C:\MyTest -Recurse | HasChanged | % { Copy-Item $_ GenerateSubDirectory(...) }
해결책을 찾았어요...그러나 성능 측면에서 최고인지는 확신할 수 없습니다.
$Source = "c:\scripts"
$Destination = "c:\test"
###################################################
###################################################
Param($Source,$Destination)
function Get-FileMD5 {
Param([string]$file)
$mode = [System.IO.FileMode]("open")
$access = [System.IO.FileAccess]("Read")
$md5 = New-Object System.Security.Cryptography.MD5CryptoServiceProvider
$fs = New-Object System.IO.FileStream($file,$mode,$access)
$Hash = $md5.ComputeHash($fs)
$fs.Close()
[string]$Hash = $Hash
Return $Hash
}
function Copy-LatestFile{
Param($File1,$File2,[switch]$whatif)
$File1Date = get-Item $File1 | foreach-Object{$_.LastWriteTimeUTC}
$File2Date = get-Item $File2 | foreach-Object{$_.LastWriteTimeUTC}
if($File1Date -gt $File2Date)
{
Write-Host "$File1 is Newer... Copying..."
if($whatif){Copy-Item -path $File1 -dest $File2 -force -whatif}
else{Copy-Item -path $File1 -dest $File2 -force}
}
else
{
#Don't want to copy this in my case..but good to know
#Write-Host "$File2 is Newer... Copying..."
#if($whatif){Copy-Item -path $File2 -dest $File1 -force -whatif}
#else{Copy-Item -path $File2 -dest $File1 -force}
}
Write-Host
}
# Getting Files/Folders from Source and Destination
$SrcEntries = Get-ChildItem $Source -Recurse
$DesEntries = Get-ChildItem $Destination -Recurse
# Parsing the folders and Files from Collections
$Srcfolders = $SrcEntries | Where-Object{$_.PSIsContainer}
$SrcFiles = $SrcEntries | Where-Object{!$_.PSIsContainer}
$Desfolders = $DesEntries | Where-Object{$_.PSIsContainer}
$DesFiles = $DesEntries | Where-Object{!$_.PSIsContainer}
# Checking for Folders that are in Source, but not in Destination
foreach($folder in $Srcfolders)
{
$SrcFolderPath = $source -replace "\\","\\" -replace "\:","\:"
$DesFolder = $folder.Fullname -replace $SrcFolderPath,$Destination
if(!(test-path $DesFolder))
{
Write-Host "Folder $DesFolder Missing. Creating it!"
new-Item $DesFolder -type Directory | out-Null
}
}
# Checking for Folders that are in Destinatino, but not in Source
foreach($folder in $Desfolders)
{
$DesFilePath = $Destination -replace "\\","\\" -replace "\:","\:"
$SrcFolder = $folder.Fullname -replace $DesFilePath,$Source
if(!(test-path $SrcFolder))
{
Write-Host "Folder $SrcFolder Missing. Creating it!"
new-Item $SrcFolder -type Directory | out-Null
}
}
# Checking for Files that are in the Source, but not in Destination
foreach($entry in $SrcFiles)
{
$SrcFullname = $entry.fullname
$SrcName = $entry.Name
$SrcFilePath = $Source -replace "\\","\\" -replace "\:","\:"
$DesFile = $SrcFullname -replace $SrcFilePath,$Destination
if(test-Path $Desfile)
{
$SrcMD5 = Get-FileMD5 $SrcFullname
$DesMD5 = Get-FileMD5 $DesFile
If(Compare-Object $srcMD5 $desMD5)
{
Write-Host "The Files MD5's are Different... Checking Write
Dates"
Write-Host $SrcMD5
Write-Host $DesMD5
Copy-LatestFile $SrcFullname $DesFile
}
}
else
{
Write-Host "$Desfile Missing... Copying from $SrcFullname"
copy-Item -path $SrcFullName -dest $DesFile -force
}
}
# Checking for Files that are in the Destinatino, but not in Source
foreach($entry in $DesFiles)
{
$DesFullname = $entry.fullname
$DesName = $entry.Name
$DesFilePath = $Destination -replace "\\","\\" -replace "\:","\:"
$SrcFile = $DesFullname -replace $DesFilePath,$Source
if(!(test-Path $SrcFile))
{
Write-Host "$SrcFile Missing... Copying from $DesFullname"
copy-Item -path $DesFullname -dest $SrcFile -force
}
}
이 파일은 약간 길지만 파일의 아카이브 비트 ---a--- 특성을 찾기 위해 확장할 수 있습니다.어쨌든 누군가에게는 합리적인 출발점일 수도 있습니다.
Function GetFileSHA ($file) {
return [Array](Get-FileHash $file -Algorithm SHA256);
}
$SourceDir = "C:\temp\1";
$TargetDir = "C:\temp\2";
$SourceFiles = Get-ChildItem -Recurse $SourceDir;
$TargetFiles = Get-ChildItem -Recurse $TargetDir;
#Source Table
$dt = New-Object System.Data.DataTable;
$dt.TableName = "SrcFiles";
$dtcol1 = New-Object system.Data.DataColumn fileId,([System.Int32]); $dt.columns.add($dtcol1);
$dtcol1.AllowDBNull = $false;
$dtcol1.AutoIncrement = $true;
$dtcol1.AutoIncrementSeed = 0;
$dtcol1.Unique = $true;
$dt.PrimaryKey = $dtcol1;
$dtcol2 = New-Object system.Data.DataColumn fileName,([string]); $dt.columns.add($dtcol2);
$dtcol3 = New-Object system.Data.DataColumn filePath,([string]); $dt.columns.add($dtcol3);
$dtcol3.Unique = $true;
$dtcol4 = New-Object system.Data.DataColumn fileHash,([string]); $dt.columns.add($dtcol4);
$dtcol5 = New-Object system.Data.DataColumn fileDate,([System.DateTime]); $dt.columns.add($dtcol5);
#Target Table
$dt2 = New-Object System.Data.DataTable;
$dt2.TableName = "TrgFiles";
$dt2col1 = New-Object system.Data.DataColumn fileId,([System.Int32]); $dt2.columns.add($dt2col1);
$dt2col1.AllowDBNull = $false;
$dt2col1.AutoIncrement = $true;
$dt2col1.AutoIncrementSeed = 0;
$dt2col1.Unique = $true;
$dt2.PrimaryKey = $dt2col1;
$dt2col2 = New-Object system.Data.DataColumn fileName,([string]); $dt2.columns.add($dt2col2);
$dt2col3 = New-Object system.Data.DataColumn filePath,([string]); $dt2.columns.add($dt2col3);
$dt2col3.Unique = $true;
$dt2col4 = New-Object system.Data.DataColumn fileHash,([string]); $dt2.columns.add($dt2col4);
$dt2col5 = New-Object system.Data.DataColumn fileDate,([System.DateTime]); $dt2.columns.add($dt2col5);
#Store file hashes and other attributes into DataTable for comparison
ForEach ($src_file in $SourceFiles){
$this_file = GetFileSHA $src_file.FullName;
$row = $dt.NewRow();
$row.fileName=($src_file).PSChildName;
$row.filePath=($src_file).FullName;
$row.fileHash=($this_file).Hash;
$row.fileDate=($src_file).LastWriteTimeUtc;
$dt.Rows.Add($row);
}
ForEach ($trg_file in $TargetFiles){
$this_file = GetFileSHA $trg_file.FullName;
$row = $dt2.NewRow();
$row.fileName=($trg_file).PSChildName;
$row.filePath=($trg_file).FullName;
$row.fileHash=($this_file).Hash;
$row.fileDate=($trg_file).LastWriteTimeUtc;
$dt2.Rows.Add($row);
}
#Compare and copy if newer/changed
ForEach ($file in $dt){
$search_dt2 = ($dt2 | Select-Object "fileName", "filePath", "fileDate", "fileHash" | Where-Object {$_.fileName -eq $file.fileName})
if ($file.fileHash -eq $search_dt2.fileHash){
$result=1;
Write-Host "File Hashes are a match - checking LastWrite status just to be safe...";
} else {
$result=2;
Write-Host "File Hashes are not a match - checking LastWrite status to see if Target is newer than source...";
}
if ($result -eq 1 -and ($file.fileDate -eq $search_dt2.fileDate)){
$result=1;
Write-Host "LastWrite status is a match. File will be skipped from copy.";
} elseif ($result -eq 1 -and $search_dt2.fileDate -gt $file.fileDate) {
$result=1;
Write-Host "LastWrite status of the target is newer. File will be skipped from copy.";
} elseif ($result -ne 1 -and $search_dt2.fileDate -gt $file.fileDate) {
$result=1;
Write-Host "LastWrite status of the target is newer than the source. File will be skipped from copy.";
} else {
$result=3;
Write-Host "File in target is older than the source and is scheduled for copy...";
}
if (Test-Path $search_dt2.filePath){
} else {
$result=4;
Write-Host "File does not exist in the target folder - file is scheduled for copy...";
}
#DO the action based on above logic
if($result -ne 1){
Copy-Item -Path $file.filePath -Destination $search_dt2.filePath -Force -Verbose
Write-Host "Code:[$result]";
} else {
Write-Host "Code:[$result]";
}
}
언급URL : https://stackoverflow.com/questions/677789/powershell-copy-item-but-only-copy-changed-files
'programing' 카테고리의 다른 글
Incorrect key file for table '/tmp/#sql_3c51_0.MYI'; try to repair it (0) | 2023.10.07 |
---|---|
mysql 디렉토리 오류 초기화 중 (0) | 2023.10.07 |
jQuery : 여러 문자열을 검색하기 위한 선택기를 포함합니다. (0) | 2023.10.07 |
XML 요소에 대한 표준 명명 규칙이 있습니까? (0) | 2023.10.07 |
AJAX 호출 시 URL을 업데이트하시겠습니까? (0) | 2023.10.07 |