Question
Recherche de Doublons par Hash
- Zedd
- Auteur du sujet
- Hors Ligne
- Membre senior
-
Réduire
Plus d'informations
- Messages : 45
- Remerciements reçus 0
il y a 7 ans 6 mois #27587
par Zedd
Recherche de Doublons par Hash a été créé par Zedd
Bonjour,
Il existe déjà pas mal de sujets sur les doublons, mais je me suis basé sur les hash pour réaliser mon script, et non aps sur le nom, la taille, etc...
Avant de poster ça dans les contributions à la communauté, je me suis dit que ce script doit être optimisable.
J'ai déjà fait de mon côté plusieurs variantes (qui recherchent le Hash après le get-childitem, qui cherchent pendant, avec un stockage du résultat dans un tableau, sans tableau, etc...). Pour l'instant c'est la version la plus \"rapide\" que j'ai.
Bien sur ça dépend aussi du nombre de fichiers à scanner, de la vitesse des disques, etc... mais peut être que le code est optimisable (par exemple le système d'exclusion en début de script, pas très sexy).
Sur un gros volume, ça consomme pas mal de RAM (je suis monté à 2-3 Go). Pour exemple, un scan de 40.000 fichiers prend environ 15-20 minutes, contre 16-18h pour 250.000 fichiers (avec plus de 50% de doublons et des fichiers allant jusqu'à 3,5Go... merci le service PAO
)
[code:1]
$Chemin = \"C:\test\"
$ExtentionLog = \"Test\"
$Exclude1 = \"*BackupPAO*\"
$Exclude2 = \"*Service_info\DOCOCS*\"
$Exclude3 = \"*Support\Powershell*\"
$Journal = \"C:\Scripts\Doublons\Journal_\" + $ExtentionLog + \".txt\"
$LogDoublon = \"C:\Scripts\Doublons\Doublons_\" + $ExtentionLog + \".txt\"
\"Voici des doublons potentiels : \" > $LogDoublon
$timeGlobal_start = Get-Date
#Etape 1
Write-Host \"Génération de la liste de tous les fichiers présents\" -ForegroundColor Green
$time_start = Get-Date
$Files = get-childitem -recurse $Chemin | where-object {(!$_.PSIsContainer) -and ($_.FullName -notlike $Exclude1) -and ($_.FullName -notlike $Exclude2) -and ($_.FullName -notlike $Exclude3)} | foreach {Get-FileHash $_.fullname | select Hash,Path}
$CompteurFiles = ($Files | measure-object).count
$time_stop = Get-Date
$timer1 = ($time_stop - $time_start)
\"Etape1 - Génération de la liste de tous les fichiers présents : $timer1\" >> $Journal
#Etape 2
$TimeDoublon_start = Get-Date
Write-Host \"Génération de la liste de chaque Hash trouvé\" -ForegroundColor Green
$HashUnique = $Files.Hash | Sort-Object –unique
$CompteHashUnique = ($HashUnique | measure-object).count
$TaillePerduTotal = 0
Write-Host \"Génération de la liste des fichiers uniquement en doublons\" -ForegroundColor Green
$ListeDesDoublons = $Files | Group-Object -Property Hash | Where-Object -FilterScript {$_.Count -gt 1} | select-object -ExpandProperty Group
$CompteurListeDesDoublons = ($ListeDesDoublons | measure-object).count
$TimeDoublon_stop = Get-Date
$timer2 = ($TimeDoublon_stop - $TimeDoublon_start)
\"Etape2 - Génération de la liste des fichiers uniquement en doublons : $timer2\" >> $Journal
#Etape 3
Write-Host \"On créer le log, trié par Hash, et on calcule le poids perdu\" -ForegroundColor Green
$TimeListe_start = Get-Date
$Tableau = @()
Foreach ($Doublon in $ListeDesDoublons)
{
$Taille = get-childitem $Doublon.Path | select Length
$obj = New-Object Psobject
$obj | Add-Member -Name \"NomComplet\" -membertype Noteproperty -Value $Doublon.Path
$obj | Add-Member -Name \"Hash\" -membertype Noteproperty -value $Doublon.Hash
$obj | Add-Member -Name \"Poids\" -membertype Noteproperty -value $Taille.Length
$Tableau += $obj
}
$Tri = $Tableau | Sort-Object -Property Poids,NomComplet -Descending | Group-Object -Property Hash #| select-object -ExpandProperty Group
$CompteurDeDoublons = ($Tri.Name | Sort-Object –unique | Measure-Object).count
Foreach ($Possibilite in $Tri)
{
$CountEspacePerdu = 0
$ChaqueDoublon = $Possibilite | select-object -ExpandProperty Group
Foreach ($FichierDoublon in $ChaqueDoublon)
{
$PoidsFichier = $FichierDoublon.Poids
$NomCompletFichier = $FichierDoublon.NomComplet
$PoidsFichierEnKilo = [math]::Round($PoidsFichier / 1024,2)
$PoidsFichierEnMega = [math]::Round($PoidsFichierEnKilo / 1024,2)
$PoidsFichierEnGiga = [math]::Round($PoidsFichierEnMega / 1024,2)
if(($PoidsFichier -ge 0) -and ($PoidsFichier -lt 1025)) {$PoidsAInscrire = \"$PoidsFichier Octets\"}
elseif(($PoidsFichier -gt 1024) -and ($PoidsFichier -lt 1048577)) {$PoidsAInscrire = \"$PoidsFichierEnKilo Ko\"}
elseif(($PoidsFichier -gt 1048576) -and ($PoidsFichier -lt 1073741825)) {$PoidsAInscrire = \"$PoidsFichierEnMega Mo\"}
elseif($PoidsFichier -gt 1073741824){$PoidsAInscrire = \"$PoidsFichierEnGiga Go\"}
\"$PoidsAInscrire - $NomCompletFichier\" >> $LogDoublon
$CountEspacePerdu = $CountEspacePerdu + $PoidsFichier
}
$CountEspacePerdu = $CountEspacePerdu - $TailleDuFichier
\"
\" >> $LogDoublon
$TaillePerduTotal = $TaillePerduTotal + $CountEspacePerdu
$CompteurDeDoublons = $CompteurDeDoublons -1
\"Il reste $CompteurDeDoublons Hash en doublon à traiter\"
}
$TimeListe_stop = Get-Date
$timer3 = ($TimeListe_stop - $TimeListe_start)
\"Etape3 - On créer le log, trié par Hash, et on calcule le poids perdu : $timer3\" >> $Journal
$timeGlobal_stop = Get-Date
$timer4 = ($timeGlobal_stop - $timeGlobal_start)
\"Exécution totale : $timer4\" >> $Journal
$TailleEnKilo = $TaillePerduTotal / 1024
$TailleEnMega = $TailleEnKilo / 1024
$TailleEnGiga = $TailleEnMega / 1024
\"
\" >> $Journal
\"$CompteurListeDesDoublons doublons pour $CompteurFiles fichiers\" >> $Journal
\"Place Perdue au total : $TaillePerduTotal Octets\" >> $Journal
\"Place Perdue au total : $TailleEnKilo Ko\">> $Journal
\"Place Perdue au total : $TailleEnMega Mo\">> $Journal
\"Place Perdue au total : $TailleEnGiga Go\">> $Journal
exit
[/code:1]<br><br>Message édité par: Zedd, à: 21/09/18 12:19
Il existe déjà pas mal de sujets sur les doublons, mais je me suis basé sur les hash pour réaliser mon script, et non aps sur le nom, la taille, etc...
Avant de poster ça dans les contributions à la communauté, je me suis dit que ce script doit être optimisable.
J'ai déjà fait de mon côté plusieurs variantes (qui recherchent le Hash après le get-childitem, qui cherchent pendant, avec un stockage du résultat dans un tableau, sans tableau, etc...). Pour l'instant c'est la version la plus \"rapide\" que j'ai.
Bien sur ça dépend aussi du nombre de fichiers à scanner, de la vitesse des disques, etc... mais peut être que le code est optimisable (par exemple le système d'exclusion en début de script, pas très sexy).
Sur un gros volume, ça consomme pas mal de RAM (je suis monté à 2-3 Go). Pour exemple, un scan de 40.000 fichiers prend environ 15-20 minutes, contre 16-18h pour 250.000 fichiers (avec plus de 50% de doublons et des fichiers allant jusqu'à 3,5Go... merci le service PAO
[code:1]
$Chemin = \"C:\test\"
$ExtentionLog = \"Test\"
$Exclude1 = \"*BackupPAO*\"
$Exclude2 = \"*Service_info\DOCOCS*\"
$Exclude3 = \"*Support\Powershell*\"
$Journal = \"C:\Scripts\Doublons\Journal_\" + $ExtentionLog + \".txt\"
$LogDoublon = \"C:\Scripts\Doublons\Doublons_\" + $ExtentionLog + \".txt\"
\"Voici des doublons potentiels : \" > $LogDoublon
$timeGlobal_start = Get-Date
#Etape 1
Write-Host \"Génération de la liste de tous les fichiers présents\" -ForegroundColor Green
$time_start = Get-Date
$Files = get-childitem -recurse $Chemin | where-object {(!$_.PSIsContainer) -and ($_.FullName -notlike $Exclude1) -and ($_.FullName -notlike $Exclude2) -and ($_.FullName -notlike $Exclude3)} | foreach {Get-FileHash $_.fullname | select Hash,Path}
$CompteurFiles = ($Files | measure-object).count
$time_stop = Get-Date
$timer1 = ($time_stop - $time_start)
\"Etape1 - Génération de la liste de tous les fichiers présents : $timer1\" >> $Journal
#Etape 2
$TimeDoublon_start = Get-Date
Write-Host \"Génération de la liste de chaque Hash trouvé\" -ForegroundColor Green
$HashUnique = $Files.Hash | Sort-Object –unique
$CompteHashUnique = ($HashUnique | measure-object).count
$TaillePerduTotal = 0
Write-Host \"Génération de la liste des fichiers uniquement en doublons\" -ForegroundColor Green
$ListeDesDoublons = $Files | Group-Object -Property Hash | Where-Object -FilterScript {$_.Count -gt 1} | select-object -ExpandProperty Group
$CompteurListeDesDoublons = ($ListeDesDoublons | measure-object).count
$TimeDoublon_stop = Get-Date
$timer2 = ($TimeDoublon_stop - $TimeDoublon_start)
\"Etape2 - Génération de la liste des fichiers uniquement en doublons : $timer2\" >> $Journal
#Etape 3
Write-Host \"On créer le log, trié par Hash, et on calcule le poids perdu\" -ForegroundColor Green
$TimeListe_start = Get-Date
$Tableau = @()
Foreach ($Doublon in $ListeDesDoublons)
{
$Taille = get-childitem $Doublon.Path | select Length
$obj = New-Object Psobject
$obj | Add-Member -Name \"NomComplet\" -membertype Noteproperty -Value $Doublon.Path
$obj | Add-Member -Name \"Hash\" -membertype Noteproperty -value $Doublon.Hash
$obj | Add-Member -Name \"Poids\" -membertype Noteproperty -value $Taille.Length
$Tableau += $obj
}
$Tri = $Tableau | Sort-Object -Property Poids,NomComplet -Descending | Group-Object -Property Hash #| select-object -ExpandProperty Group
$CompteurDeDoublons = ($Tri.Name | Sort-Object –unique | Measure-Object).count
Foreach ($Possibilite in $Tri)
{
$CountEspacePerdu = 0
$ChaqueDoublon = $Possibilite | select-object -ExpandProperty Group
Foreach ($FichierDoublon in $ChaqueDoublon)
{
$PoidsFichier = $FichierDoublon.Poids
$NomCompletFichier = $FichierDoublon.NomComplet
$PoidsFichierEnKilo = [math]::Round($PoidsFichier / 1024,2)
$PoidsFichierEnMega = [math]::Round($PoidsFichierEnKilo / 1024,2)
$PoidsFichierEnGiga = [math]::Round($PoidsFichierEnMega / 1024,2)
if(($PoidsFichier -ge 0) -and ($PoidsFichier -lt 1025)) {$PoidsAInscrire = \"$PoidsFichier Octets\"}
elseif(($PoidsFichier -gt 1024) -and ($PoidsFichier -lt 1048577)) {$PoidsAInscrire = \"$PoidsFichierEnKilo Ko\"}
elseif(($PoidsFichier -gt 1048576) -and ($PoidsFichier -lt 1073741825)) {$PoidsAInscrire = \"$PoidsFichierEnMega Mo\"}
elseif($PoidsFichier -gt 1073741824){$PoidsAInscrire = \"$PoidsFichierEnGiga Go\"}
\"$PoidsAInscrire - $NomCompletFichier\" >> $LogDoublon
$CountEspacePerdu = $CountEspacePerdu + $PoidsFichier
}
$CountEspacePerdu = $CountEspacePerdu - $TailleDuFichier
\"
\" >> $LogDoublon
$TaillePerduTotal = $TaillePerduTotal + $CountEspacePerdu
$CompteurDeDoublons = $CompteurDeDoublons -1
\"Il reste $CompteurDeDoublons Hash en doublon à traiter\"
}
$TimeListe_stop = Get-Date
$timer3 = ($TimeListe_stop - $TimeListe_start)
\"Etape3 - On créer le log, trié par Hash, et on calcule le poids perdu : $timer3\" >> $Journal
$timeGlobal_stop = Get-Date
$timer4 = ($timeGlobal_stop - $timeGlobal_start)
\"Exécution totale : $timer4\" >> $Journal
$TailleEnKilo = $TaillePerduTotal / 1024
$TailleEnMega = $TailleEnKilo / 1024
$TailleEnGiga = $TailleEnMega / 1024
\"
\" >> $Journal
\"$CompteurListeDesDoublons doublons pour $CompteurFiles fichiers\" >> $Journal
\"Place Perdue au total : $TaillePerduTotal Octets\" >> $Journal
\"Place Perdue au total : $TailleEnKilo Ko\">> $Journal
\"Place Perdue au total : $TailleEnMega Mo\">> $Journal
\"Place Perdue au total : $TailleEnGiga Go\">> $Journal
exit
[/code:1]<br><br>Message édité par: Zedd, à: 21/09/18 12:19
Connexion ou Créer un compte pour participer à la conversation.
- Laurent Dardenne
- Hors Ligne
- Modérateur
-
Réduire
Plus d'informations
- Messages : 6311
- Remerciements reçus 68
il y a 7 ans 5 mois #27591
par Laurent Dardenne
Tutoriels PowerShell
Réponse de Laurent Dardenne sur le sujet Re:Recherche de Doublons par Hash
Salut,
rapido ceci est à exclure comme usage:
[code:1]
$Tableau += $obj
[/code:1]
Plus précisément le type Array est 'immutable', dotNet recrée un tableau à chaque ajout d'item. Un type arraylist ou une collection générique évite ce pb.
Essaie déjà cette amélioration.
rapido ceci est à exclure comme usage:
[code:1]
$Tableau += $obj
[/code:1]
Plus précisément le type Array est 'immutable', dotNet recrée un tableau à chaque ajout d'item. Un type arraylist ou une collection générique évite ce pb.
Essaie déjà cette amélioration.
Tutoriels PowerShell
Connexion ou Créer un compte pour participer à la conversation.
Temps de génération de la page : 0.084 secondes
- Vous êtes ici :
-
Accueil
-
forum
-
PowerShell
-
Entraide pour les débutants
- Recherche de Doublons par Hash