Un script PowerShell pour trouver la taille du fichier et le nombre de fichiers d'un dossier avec des millions de fichiers?
Le but du script est le suivant:
- Imprimer le nombre de fichiers de manière récursive trouvé à l'intérieur d'un répertoire
(en omettant les dossiers eux-mêmes) - Imprimer le total de la somme de la taille du fichier de l'annuaire
- Pas le plantage de l'ordinateur en raison du massif de l'utilisation de la mémoire.
Jusqu'à présent (3) est la partie la plus difficile.
Voici ce que j'ai écrit et testé jusqu'à présent. Cela fonctionne parfaitement bien sur les dossiers avec une centaines, voire un millier de fichiers:
$hostname=hostname
$directory = "foo"
$dteCurrentDate = Get-Date –f "yyyy/MM/dd"
$FolderItems = Get-ChildItem $directory -recurse
$Measurement = $FolderItems | Measure-Object -property length -sum
$colitems = $FolderItems | measure-Object -property length -sum
"$hostname;{0:N2}" -f ($colitems.sum / 1MB) + "MB;" + $Measurement.count + " files;" + "$dteCurrentDate"
Sur les dossiers avec des millions de fichiers, cependant, la $colitems
variable devient tellement énorme de la collecte de l'information des millions de fichiers qu'il rend le système instable. Est-il un moyen plus efficace pour attirer et de stocker cette information?
Vous devez vous connecter pour publier un commentaire.
Si vous utilisez le streaming et le pipelining, vous devriez réduire le problème avec (3) beaucoup, parce que lorsque le flux de, chaque objet est transmis le long de la conduite et, lorsqu'ils sont disponibles et ne prennent pas beaucoup de mémoire et vous devriez être en mesure de traiter des millions de fichiers (même s'il faudra du temps).
Je ne crois pas @Stej déclaration de l'
Get-ChildItem probably reads all entries in the directory and then begins pushing them to the pipeline.
, c'est vrai. Le Pipelining est un concept fondamental de PowerShell (fournir les applets de commande, scripts, etc. soutenir). Il assure à la fois que les objets traités sont transmis le long de la canalisation, un par un comme et quand ils sont disponibles et aussi, seulement quand ils sont nécessaires.Get-ChildItem
ne va pas se comporter différemment.Un grand exemple de ceci est donné dans La compréhension du Pipeline de Windows PowerShell.
Citer, de:
De référence sur l'utilisation de
Get-ChildItem
surc:\
(environ 179516 des fichiers, pas des millions mais assez bien):L'utilisation de la mémoire après l'exécution de
$a = gci c:\ -recurse
(et ensuite de faire$a.count
) a été527,332K
.L'utilisation de la mémoire après l'exécution de
gci c:\ -recurse | measure-object
était59,452K
et n'est jamais allé au-dessus autour de80,000K
.(Mémoire de Travail Privé - de TaskManager, voir mémoire de la
powershell.exe
processus. Initialement, il était sur le22,000K
.)J'ai aussi essayé avec deux millions de fichiers (il m'a fallu un certain temps pour les créer!)
Expérience similaire:
L'utilisation de la mémoire après l'exécution de
$a = gci c:\ -recurse
( et ensuite de faire$a.count
) a été2,808,508K
.L'utilisation de la mémoire lors de l'exécution de
gci c:\ -recurse | measure-object
était308,060K
et n'est jamais allé au-dessus autour de400,000K
. Après avoir fini, il fallait faire un[GC]::Collect()
pour retourner à la22,000K
niveaux.Je suis toujours convaincu que
Get-ChildItem
et pipelining, vous pouvez obtenir en grande mémoire des améliorations, même pour des millions de fichiers.Get-ChildItem
effectivement se comporte différemment.-force
drapeau à Get-ChildItem de sorte qu'il sera lu système et les fichiers cachés (je déteste cette "fonctionnalité")...|measure-object
. Mais c'est vrai pour le cas où les répertoires n'ont pas des milliers/millions de fichiers.gci
à l'intérieur d'appels standard .NETGetFiles
et qui est assez bon marché (dans l'utilisation de la mémoire) pour nos conditions. Cependant, il est beaucoup plus différent que les conditions qui s'appliquent pour @stephen mesures (en millions de fichiers dans un répertoire).Get-ChildItem
probablement lit toutes les entrées dans le répertoire, puis commence à le pousser à la conduite. Dans le cas oùGet-ChildItem
ne fonctionne pas bien, essayez de passer .NET 4.0 et l'utilisation deEnumerateFiles
etEnumeratedDirectories
:Ici la partie la plus coûteuse est l'un avec de l'
New-Object io.FileInfo $f
, parce queEnumerateFiles
retourne uniquement les noms de fichiers. Donc, si seulement le comte de fichiers est assez, vous pouvez mettre en commentaire la ligne.Voir Débordement de Pile question Comment puis-je lancer PowerShell avec le .NET 4 runtime?
pour apprendre à l'utiliser .NET 4.0.
Vous pouvez également utiliser de la plaine de vieilles méthodes qui sont aussi rapides, mais à lire tous les fichiers dans le répertoire. Donc, cela dépend de vos besoins, il suffit de l'essayer. Plus tard, il y a comparaison de toutes les méthodes.
Comparaison:
@manojlds: le Pipelining est un concept fondamental. Mais en tant que concept, il n'a rien à voir avec les fournisseurs. Le fournisseur de système de fichiers s'appuie sur l' .NET mise en œuvre (.NET 2.0) qui n'a pas de paresseux capacités en matière d'évaluation (~ agents recenseurs). Vérifiez que vous-même.
La fonction suivante est assez cool et est rapide à calculer la taille d'un dossier, mais il ne fonctionne pas toujours (surtout quand il y a un problème de permission ou d'un trop long chemin d'accès au dossier).