Bienvenue à Blogs CodeS-SourceS Identification | Inscription | Aide

CoqBlog

.NET is good :-)
{ Blog de Gaël Covain }

Actualités

PowerShell : Compare-Object est votre amie (exemple sur synchronisation répertoire par répertoire)

Aujourd'hui je me suis retrouvé avec un besoin relativement basique : effectuer un mirroir d'un répertoire donné.

Jusque là, pas de problème, l'ami robocopy et son paramètre MIR sont plutôt sympas pour ce genre de choses :

robocopy.exe ".\Rep" "\\Dest\Mirroirs\Rep" /MIR /FFT

Seulement voilà, executer cette commande avec une destination ne contenant aucun des fichiers de la source équivaut bien évidemment à la copie de toutes les données, dans mon cas ça veut dire 9 sous-répertoires totalisant 60Go de données.
Vu le volume et la vitesse du réseau (un petit 100Mbps), je préfère faire une copie sous-répertoire par sous-répertoire vers la destination avant de mettre en place la commande de mirroir qui se chargera de garder tout celà à jour.

Rien de bien compliqué :

robocopy.exe ".\Rep\SousRep1" "\\Dest\Mirroirs\Rep\SousRep1" /ZB /E

Sauf que je suis du genre flemmard et que je n'ai pas envie de faire 9 fois la modification de la commande à la main.
L'idéal serait donc de pouvoir lancer 9 fois (je veux garder le choix du moment de démarrage de chaque copie) un script qui choissise automatiquement le premier sous-répertoire de la source qui n'existe pas encore dans la destination.
Facile avec PowerShell : vous disposez de base de la sympathique Cmdlet Compare-Object qui comme l'indique permet de faire des comparaisons entre les paramètres ReferenceObject et DifferenceObject.
C'est exactement ce qu'il nous faut, une liste de répertoires pouvant bien entendu servir d'entrée pour cette cmdlet :-)

 

Prenez ce code, Src\Rep contenant 9 sous-répertoires et Dest\Rep étant vide :

$srcDir="D:\Temp\Tests\Src\Rep"
$targetDir="D:\Temp\Tests\Dest\Rep"
Compare-Object $(dir $srcDir | where{$_.PSIsContainer}) $(dir $targetDir | where{$_.PSIsContainer})

Vous obtenez :

InputObject       SideIndicator
-----------       -------------
SousRep1          <=
SousRep2          <=
SousRep3          <=
SousRep4          <=
SousRep5          <=
SousRep6          <=
SousRep7          <=
SousRep8          <=
SousRep9          <=

SideIndicator indique de quel côté se trouve le répertoire qui manque de l'autre côté : ici nous voyons donc que les sous-répertoires n'existent que dans la source.
La même commande executée avec le sous-répertoire "SousRep1" dans le répertoire cible donnera la sortie suivante :

InputObject       SideIndicator
-----------       -------------
SousRep2          <=
SousRep3          <=
SousRep4          <=
SousRep5          <=
SousRep6          <=
SousRep7          <=
SousRep8          <=
SousRep9          <=

Si vous désirez voir les répertoires existants des 2 côtés, le paramètre IncludeEqual est fait pour vous.
Mais là ça ne nous intéresse bien évidemment pas, nous allons de toute façon filtrer sur SideIndicator = "<=".

 

Dans le cas qui nous intéresse l'utilisation sera la suivante :

# répertoire source
$srcDir="D:\Temp\Tests\Src\Rep"

# répertoire cible
$targetDir="D:\Temp\Tests\Dest\Rep"

# définition du template de commande pour Robocopy
$robocopyCommand='robocopy.exe "$srcDir\$currentFolder" "$targetDir\$currentFolder" /ZB /E'

# Execution : 
# 1) Comparaison des listes des répertoires
# 2) Filtrage pour obtenir seulement la liste de ceux absent de la destination
# 3) Sélection du premier qui se trouve dans ce cas
# 4) Execution de la commande Robocopy pour effectuer la copie
Compare-Object $(dir $srcDir | where{$_.PSIsContainer}) $(dir $targetDir | where{$_.PSIsContainer}) | where {$_.SideIndicator -eq "<="} | select -First 1 | % { $currentFolder=$_.InputObject; Invoke-Expression -Command $robocopyCommand }

 

Ce script lancera ainsi une commande différente à chaque execution :

  1. robocopy.exe "D:\Temp\Tests\Src\Rep\SousRep1" "D:\Temp\Tests\Dest\Rep\SousRep1" /ZB /E
  2. robocopy.exe "D:\Temp\Tests\Src\Rep\SousRep2" "D:\Temp\Tests\Dest\Rep\SousRep2" /ZB /E
  3. etc

Ce qui me permet de faire ma mise en place en 9 fois sans me fatiguer plus que ça.

 

L'exemple pris ici n'est pas forcément parlant (et utile) pour tout le monde mais je pense qu'il s'agit cependant d'un exemple assez intéressant de l'utilisation de Compare-Object.

Bon scripting.

Ce post vous a plu ? Ajoutez le dans vos favoris pour ne pas perdre de temps à le retrouver le jour où vous en aurez besoin :
Posted: dimanche 13 juillet 2008 00:46 par coq
Classé sous :

Commentaires

ROMELARD Fabrice a dit :

Vraiment intéressant, tu pourrais le poster sur le site :

- http://www.asp-php.net/ressources/bouts_de_code.aspx?rub=PowerShell

Ceci pour rassembler les sources et scripts PowerShell que l'on peut chercher.

Fabrice

# juillet 13, 2008 11:21

coq a dit :

Ha oui tiens, je vais voir pour faire ça.

# juillet 13, 2008 12:36
Les commentaires anonymes sont désactivés

Les 10 derniers blogs postés

- WSC08 : Le bilan, Les Photos, Les Webcasts à voir ou à revoir par Blog de Daniel TIZON [daniel] le il y a 6 heures et 46 minutes

- SharePoint et ses DB : Avez vous pensé à les "Tweaker" ? par The Mit's Blog le il y a 7 heures et 15 minutes

- NTttcp : Mesurer la vitesse d'un réseau par Blog d'Olivier Huet le il y a 7 heures et 39 minutes

- Un nouveau quizz par Matthieu MEZIL le il y a 10 heures et 23 minutes

- Webcast ADO.NET Data Services par Matthieu MEZIL le il y a 10 heures et 26 minutes

- edmx : mise à jour du modèle depuis la base par Matthieu MEZIL le il y a 14 heures et 13 minutes

- Alternatif - Mono 2.0 est arrivé! par #Rui le il y a 15 heures et 27 minutes

- Nouveaux avatars pour vos comptes CodeS-SourceS (suite) par Nix's Blog le il y a 17 heures et 32 minutes

- WSC 2008 : les Videos disponibles ! par Philippe Sentenac [MVP SharePoint] le il y a 19 heures et 40 minutes

- Visual Studio Talk Show: Visual Studio Team System par Azra [Florent Santin] le il y a 21 heures et 25 minutes