Question
[résolu] foreach
- Philippe
- Hors Ligne
- Modérateur
-
- Messages : 1778
- Remerciements reçus 21
comme tu le voi nzo, avec le script de Laurent, on lis toute arborescence et on travail sur le résultat, un peu comme on une requête sur une base de données !
pour ton script nzo, our ne pas bousculer ton approche, j'aurai simplement fait une petite modif sans pour autant changer le fonctionnement d'origine.
voici la modif :
[code:1] Get-ChildItem $($element.fullname) -Force -Recurse | Where-Object {-not $_.psiscontainer} |
[/code:1]
ca permet de gere les sous-dossiers sans erreur
et tu peut voir que l'on s'approche de la solution de laurent, qui est la meilleur approche !
mais on utilise peu (pour ne pas dire : pas du tout) le coté objet de powershell avec cette solution par rapport a celle de Laurent.
l'erreur est du au fait que quand tu fait \"$i += $_.Length\" $_ contient un objet System.IO.DirectoryInfo qui ne contient pas la propriété Lenght. d'ou l'erreur :
La propriété « Length » est introuvable sur cet objet.
avec : | Where-Object {-not $_.psiscontainer} je filtre les dossiers pour n'avoir que les objet de type System.IO.FileInfo
le code final :
[code:1]$dossier = \"c:\addons\"
$dossiers = Get-ChildItem $dossier | Where-Object {$_.psiscontainer}
$total = 0
foreach ($element in $dossiers)
{
$i=0 ;
Get-ChildItem $($element.fullname) -Force -Recurse | Where-Object {-not $_.psiscontainer} |
foreach -Process { $i += $_.Length }
Write-Host $i \"`t-->\" $($element.fullname)
$total += $i
}
$total
[/code:1]
pour finir je crois me souvenir que get-ChildItem a un bug fonctionnel qui fait planter la cmdlet lorsque des dossiers passer en argument on des caractères spéciaux. (exemple le crochet \"[\")
le script de laurent n'a pas ce probleme ! (pour les sous dossiers)
bon courage pour la suite<br><br>Message édité par: 6ratgus, à: 20/12/13 10:13
Connexion ou Créer un compte pour participer à la conversation.
- Laurent Dardenne
- Hors Ligne
- Modérateur
-
- Messages : 6311
- Remerciements reçus 68
Je doute, elle plus facile à écrire....tu peux voir que l'on s'approche de la solution de laurent, qui est la meilleur approche !
Pour s'en assurer il faudrait effectuer des tests de performance.
6ratgus écrit:
Utilise alors le paramètre Literalpath.lorsque des dossiers passer en argument on des caractères spéciaux. (exemple le crochet \"[\")
6ratgus écrit:
Je ne sais pas, je n'ai pas testéle script de laurent n'a pas ce probleme ! (pour les sous dossiers)
Tutoriels PowerShell
Connexion ou Créer un compte pour participer à la conversation.
- Laurent Dardenne
- Hors Ligne
- Modérateur
-
- Messages : 6311
- Remerciements reçus 68
[code:1]
C:\Tools\sysinternal\Du\Du.exe -v -c C:\Windows|
ConvertFrom-Csv -Delimiter ','
[/code:1]
Avec le premier code proposé le traitement prend 10 Mn, avec celle-ci 40 secondes. De manipuler le système avec des API win32 est tout de même plus efficace. Je suppose que ce soft utilise la MFT pour le calcul de la taille.
On s'aperçoit également que les fichiers cachés ne sont pas pris en compte par les différents code PS.
Comme quoi les tests ne sont pas du luxe
Tutoriels PowerShell
Connexion ou Créer un compte pour participer à la conversation.
- Philippe
- Hors Ligne
- Modérateur
-
- Messages : 1778
- Remerciements reçus 21
Moi si et ca marche bien, si le dossier racine passer en parametre ne contient pas de caractères spéciaux sinon comme tu dis il faut utilisé LiteralpathJe ne sais pas, je n'ai pas testé
[code:1]
$Grp = Get-ChildItem -Literalpath $dossier -Recurse |
Where {-not $_.PsIsContainer} |
Select DirectoryName,Length |
Group-Object -Property DirectoryName |
Foreach {
New-object PSObject -property @{
Name = $_.Name;
Size = ($_.Group|Measure-Object -Sum -Property Length).Sum
}
}
$Grp
[/code:1]
Laurent Dardenne écrit:
plus facile à écrire oui, mais moins simple a adapter pour l'affichage ou d'autre manipulation orienté \"objet\"Je doute, elle plus facile à écrire.
Pour s'en assurer il faudrait effectuer des tests de performance.
coté performance a première vu,
je dirais que ton script doit être plutôt gourment en mémoire, et encore le \"Select DirectoryName,Length\" limite la conso
par contre ton script doit plus rapide sur de grande arborescence car l'appel répéter de get-childitem doit faire perdre du temps, meme si le select, le group et new-object te ralenti
je sens que le vais faire le test sur un serveur de fichiers de plus de 100 000 fichiers et dossiers cette apres-midi
Connexion ou Créer un compte pour participer à la conversation.
- Philippe
- Hors Ligne
- Modérateur
-
- Messages : 1778
- Remerciements reçus 21
sur serveur 2003 R2 BiProc et powershell V2 :
pour 407 517 fichiers et 57 972 dossiers
avec la solution de NZO :
6 minutes 39 secondes de scan jusqu'à 20% d'utilisation CPU et 100Mo de mémoire
et l'erreur :
Get-ChildItem : The specified path, file name, or both are too long. The fully qualified file name must be less than 260 characters,
and the directory name must be less than 248 characters.
--> des nom de dossier trop long
avec la solution de Laurent :
aprés 1 heure de scan j'ai arrêté le script mais il y consommé jusqu'à 50% d'utilisation CPU (1 CPU a fond la moitié du temps) et 520Mo de mémoire
pas de message d'erreur
sur serveur 2008R2 QuadriProc et powershell V2 :
pour 170 962 fichiers et 12 389 dossiers
avec la solution de NZO :
0 minutes 47 secondes de scan jusqu'à 20% d'utilisation CPU et 50Mo de mémoire
Get-ChildItem : The specified path, file name, or both are too long. The fully qualified file name must be less than 260 characters,
and the directory name must be less than 248 characters.
--> des nom de dossier trop long
avec la solution de Laurent :
4 minutes 04 secondes de scan jusqu'à 50% d'utilisation CPU (1 CPU a fond la moitié du temps) et 330Mo de mémoire
pas de message d'erreur
Première conclusion rapide :
bien que la solution de Laurent soit la plus orienté objet, je pense que l'utilisation du group-object a fortement ralentie le scan, et consomme bien plus de mémoire
un test sans le groupe donne 1 minute de scan(et 300Mo de mémoire) donc il y 3 minutes de trie après !
a retesté avec la version 4 de powershell
Connexion ou Créer un compte pour participer à la conversation.
- Laurent Dardenne
- Hors Ligne
- Modérateur
-
- Messages : 6311
- Remerciements reçus 68
Il se peut que l'écriture sur disque des objets au format csv, réduise l'occupation mémoire.
Tutoriels PowerShell
Connexion ou Créer un compte pour participer à la conversation.
- Vous êtes ici :
-
Accueil
-
forum
-
PowerShell
-
Entraide pour les débutants
- [résolu] foreach