2009-03-24 3 views
23

変更されたファイルをコピーして行うことができることB.からそれをコピーし、以下:PowerShellのコピー項目だけ、私はディレクトリを再帰しようとしています

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チェックを行います...私は本当に私に必要なものを与えるために2つのスクリプトを一緒に配置する方法はわかりません。上記のCRCチェックが実際にこれを行う正しい方法であるかどうかもわかりません。

誰にも洞察力はありますか?

+7

私の最初の質問は、ちょうどRobocopyを使用して見たことがありますか?あなたは本当にここで非常によく設計されたホイールを再発明しています。 – EBGreen

答えて

3

私はそれがパフォーマンスの観点から最善であることを確認し解決策を見つけた...しかしない:ここでは

$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 
    } 
} 
7

は、スクリプトがより保守であることをどのようにすることができますガイドラインの一部です。

元のスクリプトをフィルタとして変換します。

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 

それとも、それらの両方は、PowerShellの固体の答えですが、それはおそらく、レバレッジRobocopyにはるかに簡単だろうサブディレクトリ

ls C:\MyTest -Recurse | HasChanged | % { Copy-Item $_ GenerateSubDirectory(...) } 
22

を生成し、別の関数を作成することができます(MSが堅牢な付属コピーアプリケーション)。

robocopy "C:\SourceDir\" "C:\DestDir\" /MIR 

でも同じことが達成されます。

+7

robocopyは私が知る限り内容を比較しません。サイズや日付スタンプに依存します。 – bart

関連する問題