2009-03-24 1 views
23

Я пытаюсь рекурсивный через каталог и скопируйте его от А до В. Это можно сделать с помощью следующих действий:Powershell Copy-Item, но только скопировать измененные файлы

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 на самом деле является правильным способом.

У кого-нибудь есть понимание?

+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 

Или вы можете создать еще одну функцию, которая создает подкаталог

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

Оба эти твердые ответы на PowerShell, но это, вероятно, будет гораздо легче всего плечами Robocopy (MS поставляется надежным копировать приложение).

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

выполнит то же самое.

+7

robocopy не сравнивает контент, насколько я могу судить. Он зависит от размеров и штампов. – bart

Смежные вопросы