Question
Stocker résultat dans une variable
- Debbia
- Auteur du sujet
- Hors Ligne
- Nouveau membre
-
- Messages : 5
- Remerciements reçus 0
Je découvre le Powershell en ce moment et je suis confronté à un problème qui me rend fou
J'ai un script tout simple qui doit récupérer les lettres des partitions et les scanner pour récuperer les fichier faisant plus de 500Mo:
[code:1]$test = Get-WmiObject Win32_LogicalDisk | select-object DeviceID
function GrosFichiers
{
foreach ($part in $test)
{Get-ChildItem $part -recurse | Sort-Object length -descending | where-object { $_.length -gt 500000000 } | ft directory,name,length -wrap –auto}
}
GrosFichiers $test
[/code:1]
Le problème c'est que quand je le lance il me retourne ceci :
Lecteur introuvable. Il n'existe aucun lecteur nommé « @{DeviceID=Z ».
à : ligne:10 caractère:16
+ {Get-ChildItem <<<< $part -recurse | Sort-Object length -descending | where-object { $_.length -gt 500000000 } | ft directory,name,length -wrap –auto}
En gros il ne récupère pas la lettre comme je le désire mais un résultat comme cela: @{DeviceID=C
Comment faire pour qu'il m'interprète cela convenablement?
Merci d'avance pour votre aide.
Cordialement.
Connexion ou Créer un compte pour participer à la conversation.
- Richard Lazaro
- Hors Ligne
- Membre platinium
-
- Messages : 530
- Remerciements reçus 0
Alors c'est tout bête, ta commande WMI retourne un tableau d'objet (si yen a plusieurs) de type Selected.System.Management.ManagementObject
Et tu as dedans une propriété (enfin une NoteProperty).
[code:1]
[PS] > $test | Get-Member
TypeName: Selected.System.Management.ManagementObject
Name MemberType Definition
----
Equals Method bool Equals(System.Object obj)
GetHashCode Method int GetHashCode()
GetType Method type GetType()
ToString Method string ToString()
DeviceID NoteProperty System.String DeviceID=C:
[/code:1]
Quand tu fais ton foreach, ta variable $part récupère un objet de ta liste d'objet.
Le problème, c'est que ce n'est pas une chaîne de caractère (string) alors que le paramètre Path de la cmdlet Get-ChildItem attend un string.
Ton objet est alors transformé en string mais pas correctement ...
Il existe deux solution, soit tu t'amuses à redéfinir la méthode ToString() de l'objet ... long et embêtant pour ce que tu as à faire.
Soit tu appels la NoteProperty de l'objet contenu dasn ta variable $path, cad :
$test = Get-WmiObject Win32_LogicalDisk | select-object DeviceID
[code:1]
$test = Get-WmiObject Win32_LogicalDisk | select-object DeviceID
function GrosFichiers
{
foreach ($part in $test)
{
Get-ChildItem $part.DeviceID -recurse | Sort-Object length -descending | where-object { $_.length -gt 500000000 } | ft directory,name,length -wrap –auto
}
}
GrosFichiers $test
[/code:1]
Voilà, normalement cela devrait fonctionner ;]
Bien Cordialement,
Richard Lazaro.
Think-MS : (Get-Life).Days | %{ Learn-More }
\\"Problems cannot be solved by the same level of thinking that created them.\\" - Albert Einstein
Connexion ou Créer un compte pour participer à la conversation.
- Debbia
- Auteur du sujet
- Hors Ligne
- Nouveau membre
-
- Messages : 5
- Remerciements reçus 0
Je viens de trouver et je dois dire que c'est tout bête mais quand on ne sait pas c'est pas évident.
Merci pour le temps passé à m'aider
Connexion ou Créer un compte pour participer à la conversation.
- Richard Lazaro
- Hors Ligne
- Membre platinium
-
- Messages : 530
- Remerciements reçus 0
Think-MS : (Get-Life).Days | %{ Learn-More }
\\"Problems cannot be solved by the same level of thinking that created them.\\" - Albert Einstein
Connexion ou Créer un compte pour participer à la conversation.
- Laurent Dardenne
- Hors Ligne
- Modérateur
-
- Messages : 6311
- Remerciements reçus 68
Richard je suis tout à fait d'accord avec ton explication, mais ici, je sais je suis pointilleux, la conversion en string est correcte, c'est le résultat qui est inadapté à l'usage.Ton objet est alors transformé en string mais pas correctement ...
De redéfinir la méthode ToString() permet justement de l'adapter (spécialiser) à cet usage.
Comme Select-object construit un objet de type PSObject, la méthode ToString de ce type renvoi une chaîne dans un format 'spécialisé'.
Richard Lazaro écrit:
Une autre approche est d'inverser le pb en déclarant sur l'objet un alias ou en choisissant un nom de membre reconnu afin de s'appuyer les mécanismes du pipeline, ici on part donc du nom du paramètre attendu, Path, et pas du type de l'objet :Le problème, c'est que ce n'est pas une chaîne de caractère (string) alors que le paramètre Path de la cmdlet Get-ChildItem attend un string.
[code:1]
#Get-ChildItem gére, via le pipeline, les membres Path et LiteralPath
#Le membre Path existe déjà sur une instance WMI
$test = Get-WmiObject Win32_LogicalDisk | select-object @{N=\"LiteralPath\";E={$_.DeviceID}}
$test[1]|Get-ChildItem
$test = Get-WmiObject Win32_LogicalDisk | Add-member -membertype aliasproperty -name LiteralPath -value DeviceID -secondvalue System.String -pass
$test[1]|Get-ChildItem
[/code:1]
Ensuite en allant plus loin on peut réécrire le code :
[code:1]
function Get-Files {
param (
#pas de position
#si on n'utilise pas le pipe on doit préciser son nom -InputObject ou -I
#le paramètre suivant sera considéré comme étant en position 0, car innommé
[Parameter(Mandatory=$true,ValueFromPipeline=$true)]
$InputObject,
[Parameter(Position=0)]
[Int64]
$size=500000000,
[switch] $Recurse,
[switch] $ForceRoot)
Process
{
if (Test-Path $_.Path)
{
if ($ForceRoot)
{cd \"$($_.Path)\\"}
$_|Get-ChildItem -recurse:$recurse |
where-object { $_.length -gt $size }
}
#else { write-Warning $_.Path}
}#process
}
Get-WmiObject Win32_LogicalDisk |
Select-Object @{N=\"Path\";E={$_.DeviceID}}|
Get-Files -size 1000 -recurse|
Sort-Object length -descending |
ft directory,name,length -wrap –auto
[/code:1]
N4rk0o, afin d'accélérer le traitement l'appel à Sort-Object doit être placé dans les derniers segments du pipeline.
La fonction Get-Files respecte la convention de nommage préconisée par MS et elle renvoie une liste de fichiers, la présentation est un autre traitement qui doit se faire au cas par cas et en dehors de la fonction.
Autre chose, l'accés aux lecteurs se fait dans le répertoire courant, il peut donc ne pas être à la racine, soit tu déclares un switch pour traiter le cas soit tu précises le comportement dans la doc.
On déclare $Recurse pour le propager ou non lors de l'appel à Get-ChildItem, etc, etc.
Cela nécessite de passer un peu plus de temps à coder, l'avantage est qu'en procédant de cette manière à terme tu gagneras du temps.
Ici l'appel à $part.DeviceID est le plus pratique, mais l'objet traité dans la fonction est lié à un appel préalable à Win32_LogicalDisk, un autre avantage d'utiliser les mécanismes du pipeline est qu'ils permettent de varier la source des objets.
C'est vrai que lorsqu'on débute tout ça n'est pas évident à saisir et peut même embrouiller.
Une fois que l'on compris ces qq principes de base on n'utilise plus PowerShell de la même manière.
Tutoriels PowerShell
Connexion ou Créer un compte pour participer à la conversation.
- Debbia
- Auteur du sujet
- Hors Ligne
- Nouveau membre
-
- Messages : 5
- Remerciements reçus 0
J'ai bien pris note de tes remarques
Cordialement.
Connexion ou Créer un compte pour participer à la conversation.
- Vous êtes ici :
-
Accueil
-
forum
-
PowerShell
-
Entraide pour les débutants
- Stocker résultat dans une variable