2009-03-24 8 views
23

Je suis en train de récursivité dans un répertoire et copiez-le de A à B. Cela peut être fait avec les éléments suivants:Powershell Copy-Item, mais seulement copier les fichiers modifiés

Copy-Item C:\MyTest C:\MyTest2 –recurse 

Je veux être en mesure de bien Copiez uniquement les nouveaux fichiers (ceux qui existent dans src mais pas dest) et copiez uniquement les fichiers qui ont été modifiés en fonction d'une vérification CRC et non d'un horodatage.

$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() 

Ce code me donne un chèque de CRC sur un fichier spécifique ... Je ne suis pas sûr comment mettre les deux scripts ensemble pour me donner vraiment ce que je dois. Je ne sais pas non plus si le contrôle CRC ci-dessus est réellement la bonne façon de le faire.

Quelqu'un a-t-il un aperçu?

+7

Ma première question est de savoir si vous avez utilisé Robocopy? Vous réinventez vraiment une roue très bien conçue ici. – EBGreen

Répondre

3

J'ai trouvé une solution ... mais pas sûr qu'il est le meilleur du point de vue de la performance:

$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

Voici quelques-unes des lignes directrices comment vous pouvez votre script pour être plus maintenable.

Convertissez le script d'origine en filtre. Puis, filtrez simplement tous les fichiers mis à jour et copiez-les.

# 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 

Ou vous pouvez créer une autre fonction qui génère sous répertoire

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

Ces deux sont des réponses solides pour Powershell, mais il serait sans doute beaucoup plus facile de simplement l'effet de levier Robocopy (MS Fourni robuste copie de demande).

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

accomplirait la même chose.

+7

robocopy ne compare pas le contenu autant que je peux dire. Il repose sur des tailles et des timbres de date. – bart

Questions connexes