Question Question débutant de base qui vient de commencer

Plus d'informations
il y a 11 ans 3 mois #18594 par gsa
Bonjour,

je viens de me mettre au PS. J'ai acheté le livre Guide de Ref., que j'ai recu ce matin je n'en suis qu'au début (chap2).

Je joue un peu avec la commande Get-ChildItem pour essayer de me familiariser avec la syntaxe et la manipulation des propriétés.

je me suis donné le problème suivant: Faire la somme des tailles des fichiers qui commencent par J.( juste parce que je suis dans le répertoire courant et qu'il n'y a pas trop de fichier en J) et que cela permet aussi de rajouter un pipe avec le Where-Object

le tout en une seule ligne de commande bien \"pipée\" !

je pensais faire un truc du genre


count=0 # ok il y aura 2 lignes avec l'init ;)
count+= $count+=Get-ChildItem | Where-Object {$_.Name -like \"j*\"}| extraction de la propriété Lenght

mais je n'y arrive pas.

En decomposant, je me suis rendu compte d'une chose


$count=Get-ChildItem | Where-Object {$_.Name -like \"j*\"} me donne le nombre de fichiers (ok 6)

si je veux voir lequels , je vais les afficher
Get-ChildItem | Where-Object {$_.Name -like \"j*\"}|ft name, length

si je je fais un count de cela
$count=Get-ChildItem| Where-Object {$_.Name -like \"j*\"} |ft name, length

$count vaut 10, il me compte des lignes en plus lors de l'affichage

donc je ne peux pas \"Counter\" avec un affichage, il faut donc que je récupère la propriété Length sans l'afficher.



Je suis un peu confus car pour le name on peut faire un

Get-ChildItem -name

qui équivaut à Get-ChildItem | ft name


mais pas Get-ChildItem -Length

il faut passer par Get-ChildItem | ft Length






j'ai essayé de jouer avec le propriété Lenght comme cela

$count+=(Get-ChildItem|Where-Object{$_.name -like \"j*\"}).Length

$count =6

puis

$count+=Get-ChildItem|(Where-Object{$_.name -like \"j*\"}).Length

qui n'est pas autorisé



Entre temps j'ai trouvé la commande Measure-Object, mais j'aimerai y arriver sans elle, puisque le résultat m'importe peu finalement, mais plus la facon de l'obtenir. Afin de bien comprendre les choses



je n'ai pas encore lu la partie Tableau du Chap2 , peut etre que la solution serait la. Mais la puissance du piping m'a déjà tellement impressionné que j'en demande peut etre trop ?


Merci pour vos lumières<br><br>Message édité par: gsa, à: 11/12/14 17:22

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

Plus d'informations
il y a 11 ans 3 mois #18595 par Laurent Dardenne
Salut,
gsa écrit:

$count=Get-ChildItem | Where-Object {$_.Name -like \&quot;j*\&quot;} me donne le nombre de fichiers (ok 6)

Ces instructions renvoient un ou plusieurs objets, $count peut donc contenir un tableau.
Si c'est un tableau, il possède la propriété Count, sinon il faut s'assurer de tjr recevoir un tableau, en utilisant @( instructions )
[code:1]
$Result=@( Get-ChildItem | Where-Object {$_.Name -like \&quot;j*\&quot;} )
$Result.Count
[/code:1]
Note : Ce qui complique un peu les choses est que cette écriture dépend de la version de PS utilisée.
gsa écrit:

$count vaut 10, il me compte des lignes en plus lors de l'affichage

Les cmdlets Format-xxx renvoient des objets spécialisés interprétés par la console lors de l'affichage.
Cela a donc peut d'intérêts :
[code:1]$result=cmdlet|Format-xxx[/code:1]
Mais ceci en a un :
[code:1]
cmdlet|Format-xxx
[/code:1]
gsa écrit:

Je suis un peu confus car pour le name on peut faire un
Get-ChildItem -name

Il ne faut pas confondre le nom d'un paramètre d'un cmdlet/fonction avec un nom de propriété d'un objet.
[code:1]
#renvoie la liste des paramètres du cmdlet
(get-command Get-ChildItem).Parameters

$result=Get-ChildItem $Pshome
#renvoie la liste des membres (propriétés/méthodes) d'un objet
$result|get-member
[/code:1]
gsa écrit:

Entre temps j'ai trouvé la commande Measure-Object

Pour connaitre le nombre d'élément d'une collection (tableau d'objets), la propriété Count existe le plus souvent.
Tu peux effectivement l'utiliser pour calculer la somme de la propriété Length de chaque objet contenu dans ton tableau (collection d'objets).

Tutoriels PowerShell

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

Plus d'informations
il y a 11 ans 3 mois #18599 par gsa
merci Laurent d'avoir pris le temps de me répondre

j'ai bien tourné en rond,et puis je suis tombé sur la commande Foreach-object je me disais que c'était pil poil ce que je cherchais,

$somme=0
Get-ChildItem | Where-Object {$_.Name -like \&quot;j*\&quot;} |$somme+= ForEach-Object ($_.Length)

presque bon l'idée était la, il fallait trouver la syntaxe...

et voila
Get-ChildItem | Where-Object {$_.Name -like \&quot;j*\&quot;} | ForEach-Object {$somme+=$_.Length}

C'est tout bête, mais ce petit exercice m'a permis de comprendre plein de choses.

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

Plus d'informations
il y a 11 ans 3 mois #18600 par Laurent Dardenne
gsa écrit:

merci Laurent d'avoir pris le temps de me répondre

De rien.
gsa écrit:

j'ai bien tourné en rond

Cela fait partie de l'apprentissage ;-)
gsa écrit:

[code:1]
$somme=0
Get-ChildItem | Where-Object {$_.Name -like \&quot;j*\&quot;} |$somme+= ForEach-Object ($_.Length)
[/code:1]
presque bon l'idée était la

Désolé de te décevoir, mais 'l'idée' n'est pas là.
Un pipeline, tel que celui utilisé, ne peut contenir que des commandes (cmdlet/function,etc) le gérant. Une affectation n'en fait pas partie.

Si tu as compris le principe de Where-Oobject, il 'suffit' de l'appliquer à ForEach-Object, et autres cmdlet xxx-Object.
Et comme ce n'est pas le cas et sans vouloir t'offenser, cela me laisse l'impression que 'c'est tombé en marche'.
Le tâtonnement circulaire est aussi une forme d'apprentissage.

Ceci dit, ta construction est tout à fait sensée :
[code:1]
Get-ChildItem | Name -like \&quot;j*\&quot; | $somme+= $_.Length
[/code:1]
Mais n'est pas reconnu par la syntaxe de Powershell.
A la lecture on sait à peu près ce qu'on veut faire, mais ainsi formulé Powershell ne sait pas comment le faire.

Autres constructions possibles :
[code:1]
$somme=0
foreach ( $File in Get-ChildItem | Where-Object {$_.Name -like \&quot;j*\&quot;})
{
$somme+= $File.Length
}
$Somme

$Somme=Get-ChildItem | Where-Object {$_.Name -like \&quot;j*\&quot;} |Measure-Object -Property Length -Sum
$Somme.Sum
[/code:1]<br><br>Message édité par: Laurent Dardenne, à: 12/12/14 17:05

Tutoriels PowerShell

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

Plus d'informations
il y a 11 ans 3 mois #18602 par gsa
Bonjour Laurent,

C'est la que ca devient intéressant !


Car effectivement c'est tombé en marche, mais je ne comprends pas pourquoi.

Un pipeline, tel que celui utilisé, ne peut contenir que des commandes (cmdlet/function,etc) le gérant. Une affectation n'en fait pas partie.


Est-ce que l'unique raison c'est qu'un pipe ne pas contenir d'affectation ?


Si tu as compris le principe de Where-Object, il 'suffit' de l'appliquer à ForEach-Object, et autres cmdlet xxx-Object.


Et bien je ne suis pas si sur de l'avoir compris.

Mais je vais travailler sur ta solution et la décortiquer.

merci

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

Plus d'informations
il y a 11 ans 3 mois #18605 par Laurent Dardenne
gsa écrit:

Car effectivement c'est tombé en marche, mais je ne comprends pas pourquoi.

On est d'accord :-)
gsa écrit:

Est-ce que l'unique raison c'est qu'un pipe ne pas contenir d'affectation ?

le principe du pipeline est d'émettre une donnée, c'est similaire à une course de relais :
\&quot;Un relais est une course où chaque membre d'une équipe court l’un après l’autre, l'enchaînement se faisant par le « passage de témoin » \&quot;
Si l'un des participants garde le témoin, la course n'a plus de raison d'être ( sous cette forme en tout cas).
Une affectation ne transmet pas l'information dans le pipeline.

Un pipeline est porté par le symbole '|' (Alt-Gr + 6), il faut donc que les deux, au minimum, participant du pipeline puisse y lire et y écrire.
Un cmdlet sait le faire, pas une instruction du langage, sauf dans le premier segment :
[code:1]
10|Foreach { Write-host \&quot;Objet courant =$_\&quot;}
#Objet courant =10
[/code:1]
Mais ceci :
[code:1]
|$somme+= ForEach-Object ($_.Length)
[/code:1]
Ne sait pas communiquer avec le pipeline ('récupérer le témoin et le passer au suivant').

Ceci dit une affectation peut récupérer le résultat d'un pipeline :
[code:1]
$Result=10|Foreach { $_ *2}
$Rresult
#20
[/code:1]
Mais ici elle n'est pas un élément constituant du pipeline, on récupère l'information, mais le pipeline n'existe plus, car il est terminé.
gsa écrit:

Et bien je ne suis pas si sur de l'avoir compris.

Il est possible d'exécuter une instruction du langage dans le pipeline, MAIS on doit utiliser un cmdlet pour cela.
Celui-ci recoit un objet et peut le traiter en exécutant du code qui est défini par un bloc de script (scriptblock): '{ instructions }'
[code:1]

cmdlet -Parameter { instructions }

ForEach-Object -Process { instructions }

ForEach-Object -Process {$somme+=$_.Length}
#ou
ForEach-Object {$somme+=$_.Length}

#ou encore
#Variable de type scriptblock
$MonTraitementScriptBlock={$somme+=$_.Length}
ForEach-Object -Process $MonTraitementScriptBlock
ForEach-Object $MonTraitementScriptBlock

#Déclare une variable contenant du code
$ScriptBlock={10+3}

#Affiche le code
$ScriptBlock
#10+3

#exécute le code contenu dans la variable
&amp;$ScriptBlock
#13

10+3
#13
[/code:1]
Le cmdlet Foreach-Object attend en paramètre du code, c'est à dire le traitement que tu veux effectuer sur le ou les objets courants recus du pipeline.
Une écriture équivalente sans usage du pipeline :
[code:1]
$somme=0
#Boucle sur tous les objets
foreach ($Item in Get-ChildItem)
{
#Test
if ($Item.Name -like \&quot;j*\&quot;«»)
#Code du traitement
{
Write-Warning \&quot;objet reçu=$Item\&quot;
$somme+=$Item.Length
}
}
[/code:1]
Voir aussi les première page de ce tutoriel .

Tutoriels PowerShell

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

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