Question [résolu] foreach

Plus d'informations
il y a 12 ans 3 mois #16672 par Philippe
Réponse de Philippe sur le sujet Re:foreach
Merci Laurent pour t'est bon conseil :)

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.

Plus d'informations
il y a 12 ans 3 mois #16674 par Laurent Dardenne
Réponse de Laurent Dardenne sur le sujet Re:foreach
6ratgus écrit:

...tu peux voir que l'on s'approche de la solution de laurent, qui est la meilleur approche !

Je doute, elle plus facile à écrire.
Pour s'en assurer il faudrait effectuer des tests de performance.
6ratgus écrit:

lorsque des dossiers passer en argument on des caractères spéciaux. (exemple le crochet \&quot;[\&quot;)

Utilise alors le paramètre Literalpath.
6ratgus écrit:

le script de laurent n'a pas ce probleme ! (pour les sous dossiers)

Je ne sais pas, je n'ai pas testé :)

Tutoriels PowerShell

Connexion ou Créer un compte pour participer à la conversation.

Plus d'informations
il y a 12 ans 3 mois #16676 par Laurent Dardenne
Réponse de Laurent Dardenne sur le sujet Re:foreach
Une autre approche, basée sur un outil externe de sysinternal :
[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.

Plus d'informations
il y a 12 ans 3 mois #16678 par Philippe
Réponse de Philippe sur le sujet Re:foreach
Laurent Dardenne écrit:

Je ne sais pas, je n'ai pas testé :)

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é Literalpath

[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:

Je doute, elle plus facile à écrire.

Pour s'en assurer il faudrait effectuer des tests de performance.

plus facile à écrire oui, mais moins simple a adapter pour l'affichage ou d'autre manipulation orienté \&quot;objet\&quot;

coté performance a première vu,
je dirais que ton script doit être plutôt gourment en mémoire, et encore le \&quot;Select DirectoryName,Length\&quot; 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.

Plus d'informations
il y a 12 ans 3 mois #16703 par Philippe
Réponse de Philippe sur le sujet Re:foreach
test de performance

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.
--&gt; 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.
--&gt; 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.

Plus d'informations
il y a 12 ans 3 mois #16706 par Laurent Dardenne
Réponse de Laurent Dardenne sur le sujet Re:foreach
Merci pour ce test. Peux-tu l'effectuer, quand tu auras le temps, avec la version basée sur le programme Du.exe ?
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.

Temps de génération de la page : 0.068 secondes
Propulsé par Kunena