Share via


about_Pipelines

Description courte

Combinaison de commandes dans des pipelines dans PowerShell

Description longue

Un pipeline est une série de commandes connectées par des opérateurs de pipeline (|) (ASCII 124). Chaque opérateur de pipeline envoie les résultats de la commande précédente à la commande suivante.

La sortie de la première commande peut être envoyée pour traitement en tant qu’entrée de la deuxième commande. Et cette sortie peut être envoyée à une autre commande. Le résultat est une chaîne de commande ou un pipeline complexe composé d’une série de commandes simples.

Par exemple,

Command-1 | Command-2 | Command-3

Dans cet exemple, les objets qui Command-1 émettent sont envoyés à Command-2. Command-2 traite les objets et les envoie à Command-3. Command-3 traite les objets et les envoie dans le pipeline. Étant donné qu’il n’y a plus de commandes dans le pipeline, les résultats sont affichés dans la console.

Dans un pipeline, les commandes sont traitées dans l’ordre de gauche à droite. Le traitement est géré comme une seule opération et la sortie s’affiche au fur et à mesure de sa génération.

Voici un exemple simple. La commande suivante obtient le processus du Bloc-notes, puis l’arrête.

Par exemple,

Get-Process notepad | Stop-Process

La première commande utilise l’applet Get-Process de commande pour obtenir un objet représentant le processus du Bloc-notes. Il utilise un opérateur de pipeline (|) pour envoyer l’objet de processus à l’applet Stop-Process de commande, ce qui arrête le processus du Bloc-notes. Notez que la Stop-Process commande n’a pas de paramètre Name ou ID pour spécifier le processus, car le processus spécifié est envoyé via le pipeline.

Cet exemple de pipeline obtient les fichiers texte dans le répertoire actif, sélectionne uniquement les fichiers de plus de 10 000 octets, les trie par longueur et affiche le nom et la longueur de chaque fichier dans un tableau.

Get-ChildItem -Path *.txt |
  Where-Object {$_.length -gt 10000} |
    Sort-Object -Property length |
      Format-Table -Property name, length

Ce pipeline se compose de quatre commandes dans l’ordre spécifié. L’illustration suivante montre la sortie de chaque commande à mesure qu’elle est passée à la commande suivante dans le pipeline.

Get-ChildItem -Path *.txt
| (FileInfo objects for *.txt)
V
Where-Object {$_.length -gt 10000}
| (FileInfo objects for *.txt)
| (      Length > 10000      )
V
Sort-Object -Property Length
| (FileInfo objects for *.txt)
| (      Length > 10000      )
| (     Sorted by length     )
V
Format-Table -Property name, length
| (FileInfo objects for *.txt)
| (      Length > 10000      )
| (     Sorted by length     )
| (   Formatted in a table   )
V

Name                       Length
----                       ------
tmp1.txt                    82920
tmp2.txt                   114000
tmp3.txt                   114000

Utilisation de pipelines

La plupart des applets de commande PowerShell sont conçues pour prendre en charge les pipelines. Dans la plupart des cas, vous pouvez diriger les résultats d’une applet de commande Get vers une autre applet de commande du même nom. Par exemple, vous pouvez diriger la sortie de l’applet Get-Service de commande vers les Start-Service applets de commande ou Stop-Service .

Cet exemple de pipeline démarre le service WMI sur l’ordinateur :

Get-Service wmi | Start-Service

Pour un autre exemple, vous pouvez diriger la sortie de Get-Item ou Get-ChildItem du fournisseur de Registre PowerShell vers l’applet de New-ItemProperty commande. Cet exemple ajoute une nouvelle entrée de Registre, NoOfEmployees, avec la valeur 8124, à la clé de Registre MyCompany .

Get-Item -Path HKLM:\Software\MyCompany |
  New-ItemProperty -Name NoOfEmployees -Value 8124

La plupart des applets de commande de l’utilitaire, telles que Get-Member, Where-Object, Sort-ObjectGroup-Object, et Measure-Object sont utilisées presque exclusivement dans les pipelines. Vous pouvez diriger n’importe quel type d’objet vers ces applets de commande. Cet exemple montre comment trier tous les processus sur l’ordinateur en fonction du nombre de handles ouverts dans chaque processus.

Get-Process | Sort-Object -Property handles

Vous pouvez diriger des objets vers les applets de commande de mise en forme, d’exportation et de sortie, telles que Format-List, Format-Table, Export-ClixmlExport-CSVet Out-File.

Cet exemple montre comment utiliser l’applet Format-List de commande pour afficher une liste de propriétés pour un objet de processus.

Get-Process winlogon | Format-List -Property *

Vous pouvez également diriger la sortie des commandes natives vers les applets de commande PowerShell. Par exemple :

PS> ipconfig.exe | Select-String -Pattern 'IPv4'

   IPv4 Address. . . . . . . . . . . : 172.24.80.1
   IPv4 Address. . . . . . . . . . . : 192.168.1.45
   IPv4 Address. . . . . . . . . . . : 100.64.108.37

Important

Les flux Réussite et Erreur sont similaires aux flux stdin et stderr d’autres shells. Toutefois, stdin n’est pas connecté au pipeline PowerShell pour l’entrée. Pour plus d’informations, consultez about_Redirection.

Avec un peu de pratique, vous constaterez que la combinaison de commandes simples dans des pipelines fait gagner du temps et de la saisie, et rend votre script plus efficace.

Fonctionnement des pipelines

Cette section explique comment les objets d’entrée sont liés aux paramètres d’applet de commande et traités pendant l’exécution du pipeline.

Accepte l’entrée de pipeline

Pour prendre en charge le pipeline, l’applet de commande de réception doit avoir un paramètre qui accepte l’entrée de pipeline. Utilisez la Get-Help commande avec les options Full ou Parameter pour déterminer les paramètres d’une applet de commande qui acceptent l’entrée de pipeline.

Par exemple, pour déterminer les paramètres de l’applet de commande qui acceptent l’entrée Start-Service de pipeline, tapez :

Get-Help Start-Service -Full

ou

Get-Help Start-Service -Parameter *

L’aide de l’applet Start-Service de commande indique que seuls les paramètres InputObject et Name acceptent l’entrée de pipeline.

-InputObject <ServiceController[]>
Specifies ServiceController objects representing the services to be started.
Enter a variable that contains the objects, or type a command or expression
that gets the objects.

Required?                    true
Position?                    0
Default value                None
Accept pipeline input?       True (ByValue)
Accept wildcard characters?  false

-Name <String[]>
Specifies the service names for the service to be started.

The parameter name is optional. You can use Name or its alias, ServiceName,
or you can omit the parameter name.

Required?                    true
Position?                    0
Default value                None
Accept pipeline input?       True (ByPropertyName, ByValue)
Accept wildcard characters?  false

Lorsque vous envoyez des objets via le pipeline à Start-Service, PowerShell tente d’associer les objets aux paramètres InputObject et Name .

Méthodes d’acceptation de l’entrée de pipeline

Les paramètres d’applet de commande peuvent accepter l’entrée de pipeline de deux façons différentes :

  • ByValue : le paramètre accepte les valeurs qui correspondent au type .NET attendu ou qui peuvent être converties en ce type.

    Par exemple, le paramètre Name de accepte l’entrée de Start-Service pipeline par valeur. Il peut accepter des objets de chaîne ou des objets qui peuvent être convertis en chaînes.

  • ByPropertyName : le paramètre accepte l’entrée uniquement lorsque l’objet d’entrée a une propriété du même nom que le paramètre.

    Par exemple, le paramètre Name de peut accepter des Start-Service objets qui ont une propriété Name . Pour répertorier les propriétés d’un objet, dirigez-le vers Get-Member.

Certains paramètres peuvent accepter des objets par valeur ou par nom de propriété, ce qui facilite la prise d’entrée à partir du pipeline.

Liaison de paramètres

Lorsque vous dirigez des objets d’une commande vers une autre commande, PowerShell tente d’associer les objets redirigés à un paramètre de l’applet de commande de réception.

Le composant de liaison de paramètres de PowerShell associe les objets d’entrée aux paramètres d’applet de commande en fonction des critères suivants :

  • Le paramètre doit accepter l’entrée d’un pipeline.
  • Le paramètre doit accepter le type d’objet envoyé ou un type qui peut être converti en type attendu.
  • Le paramètre n’a pas été utilisé dans la commande .

Par exemple, l’applet Start-Service de commande a de nombreux paramètres, mais seulement deux d’entre eux, Name et InputObject , acceptent l’entrée de pipeline. Le paramètre Name accepte des chaînes et le paramètre InputObject accepte les objets de service. Par conséquent, vous pouvez diriger des chaînes, des objets de service et des objets avec des propriétés qui peuvent être converties en objets de chaîne ou de service.

PowerShell gère la liaison de paramètres aussi efficacement que possible. Vous ne pouvez pas suggérer ou forcer la liaison de PowerShell à un paramètre spécifique. La commande échoue si PowerShell ne peut pas lier les objets redirigés.

Pour plus d’informations sur la résolution des erreurs de liaison, consultez Examen des erreurs de pipeline plus loin dans cet article.

Traitement un à la fois

Le pipage d’objets vers une commande est similaire à l’utilisation d’un paramètre de la commande pour envoyer les objets. Examinons un exemple de pipeline. Dans cet exemple, nous utilisons un pipeline pour afficher une table d’objets de service.

Get-Service | Format-Table -Property Name, DependentServices

D’un point de vue fonctionnel, cela équivaut à utiliser le paramètre InputObject de Format-Table pour envoyer la collection d’objets.

Par exemple, nous pouvons enregistrer la collection de services dans une variable passée à l’aide du paramètre InputObject .

$services = Get-Service
Format-Table -InputObject $services -Property Name, DependentServices

Ou nous pouvons incorporer la commande dans le paramètre InputObject .

Format-Table -InputObject (Get-Service) -Property Name, DependentServices

Toutefois, il y a une différence importante. Lorsque vous dirigez plusieurs objets vers une commande, PowerShell envoie les objets à la commande un par un. Lorsque vous utilisez un paramètre de commande, les objets sont envoyés en tant qu’objet de tableau unique. Cette différence mineure a des conséquences importantes.

Lors de l’exécution d’un pipeline, PowerShell énumère automatiquement tout type qui implémente l’interface IEnumerable et envoie les membres via le pipeline un par un. L’exception est [hashtable], qui nécessite un appel à la GetEnumerator() méthode .

Dans les exemples suivants, un tableau et une table de hachage sont redirigés vers l’applet Measure-Object de commande pour compter le nombre d’objets reçus du pipeline. Le tableau a plusieurs membres, et la table de hachage a plusieurs paires clé-valeur. Seul le tableau est énuméré un par un.

@(1,2,3) | Measure-Object
Count    : 3
Average  :
Sum      :
Maximum  :
Minimum  :
Property :
@{"One"=1;"Two"=2} | Measure-Object
Count    : 1
Average  :
Sum      :
Maximum  :
Minimum  :
Property :

De même, si vous dirigez plusieurs objets de processus de l’applet Get-Process de commande vers l’applet Get-Member de commande, PowerShell envoie chaque objet de processus, un par un, à Get-Member. Get-Member affiche la classe .NET (type) des objets de processus, ainsi que leurs propriétés et méthodes.

Get-Process | Get-Member
TypeName: System.Diagnostics.Process

Name      MemberType     Definition
----      ----------     ----------
Handles   AliasProperty  Handles = Handlecount
Name      AliasProperty  Name = ProcessName
NPM       AliasProperty  NPM = NonpagedSystemMemorySize
...

Notes

Get-Member élimine les doublons. Par conséquent, si les objets sont tous du même type, il n’affiche qu’un seul type d’objet.

Toutefois, si vous utilisez le paramètre InputObject de Get-Member, Get-Member reçoit un tableau d’objets System.Diagnostics.Process en tant qu’unité unique. Il affiche les propriétés d’un tableau d’objets. (Notez le symbole de tableau ([]) après le nom du type System.Object .)

Par exemple,

Get-Member -InputObject (Get-Process)
TypeName: System.Object[]

Name               MemberType    Definition
----               ----------    ----------
Count              AliasProperty Count = Length
Address            Method        System.Object& Address(Int32 )
Clone              Method        System.Object Clone()
...

Ce résultat n’est peut-être pas celui que vous avez prévu. Mais une fois que vous avez compris, vous pouvez l’utiliser. Par exemple, tous les objets de tableau ont une propriété Count . Vous pouvez l’utiliser pour compter le nombre de processus en cours d’exécution sur l’ordinateur.

Par exemple,

(Get-Process).count

Il est important de se rappeler que les objets envoyés dans le pipeline sont remis un par un.

Utilisation de commandes natives dans le pipeline

PowerShell vous permet d’inclure des commandes externes natives dans le pipeline. Toutefois, il est important de noter que le pipeline de PowerShell est orienté objet et ne prend pas en charge les données octets brutes.

Le fait de rediriger ou de rediriger la sortie d’un programme natif qui génère des données d’octet brutes convertit la sortie en chaînes .NET. Cette conversion peut endommager la sortie des données brutes.

Pour contourner ce problème, appelez les commandes natives à l’aide cmd.exe /c| de ou sh -c et des opérateurs et > fournis par l’interpréteur de commandes natif.

Examen des erreurs de pipeline

Lorsque PowerShell ne peut pas associer les objets redirigés à un paramètre de l’applet de commande de réception, la commande échoue.

Dans l’exemple suivant, nous essayons de déplacer une entrée de Registre d’une clé de Registre vers une autre. L’applet Get-Item de commande obtient le chemin de destination, qui est ensuite redirigé vers l’applet de Move-ItemProperty commande. La Move-ItemProperty commande spécifie le chemin d’accès actuel et le nom de l’entrée de Registre à déplacer.

Get-Item -Path HKLM:\Software\MyCompany\sales |
Move-ItemProperty -Path HKLM:\Software\MyCompany\design -Name product

La commande échoue et PowerShell affiche le message d’erreur suivant :

Move-ItemProperty : The input object can't be bound to any parameters for
the command either because the command doesn't take pipeline input or the
input and its properties do not match any of the parameters that take
pipeline input.
At line:1 char:23
+ $a | Move-ItemProperty <<<<  -Path HKLM:\Software\MyCompany\design -Name p

Pour investiguer, utilisez l’applet Trace-Command de commande pour suivre le composant de liaison de paramètres de PowerShell. L’exemple suivant trace la liaison de paramètre pendant l’exécution du pipeline. Le paramètre PSHost affiche les résultats de trace dans la console et le paramètre FilePath envoie les résultats de la trace au fichier pour debug.txt une référence ultérieure.

Trace-Command -Name ParameterBinding -PSHost -FilePath debug.txt -Expression {
  Get-Item -Path HKLM:\Software\MyCompany\sales |
    Move-ItemProperty -Path HKLM:\Software\MyCompany\design -Name product
}

Les résultats de la trace sont longs, mais ils montrent les valeurs liées à l’applet Get-Item de commande, puis les valeurs nommées liées à l’applet Move-ItemProperty de commande.

...
BIND NAMED cmd line args [`Move-ItemProperty`]
BIND arg [HKLM:\Software\MyCompany\design] to parameter [Path]
...
BIND arg [product] to parameter [Name]
...
BIND POSITIONAL cmd line args [`Move-ItemProperty`]
...

Enfin, il indique que la tentative de liaison du chemin d’accès au paramètre Destination de Move-ItemProperty a échoué.

...
BIND PIPELINE object to parameters: [`Move-ItemProperty`]
PIPELINE object TYPE = [Microsoft.Win32.RegistryKey]
RESTORING pipeline parameter's original values
Parameter [Destination] PIPELINE INPUT ValueFromPipelineByPropertyName NO
COERCION
Parameter [Credential] PIPELINE INPUT ValueFromPipelineByPropertyName NO
COERCION
...

Utilisez l’applet Get-Help de commande pour afficher les attributs du paramètre Destination .

Get-Help Move-ItemProperty -Parameter Destination

-Destination <String>
    Specifies the path to the destination location.

    Required?                    true
    Position?                    1
    Default value                None
    Accept pipeline input?       True (ByPropertyName)
    Accept wildcard characters?  false

Les résultats montrent que Destination accepte uniquement l’entrée de pipeline « par nom de propriété ». Par conséquent, l’objet redirigé doit avoir une propriété nommée Destination.

Utilisez Get-Member pour voir les propriétés de l’objet provenant de Get-Item.

Get-Item -Path HKLM:\Software\MyCompany\sales | Get-Member

La sortie indique que l’élément est un objet Microsoft.Win32.RegistryKey qui n’a pas de propriété Destination . Cela explique pourquoi la commande a échoué.

Le paramètre Path accepte l’entrée de pipeline par nom ou par valeur.

Get-Help Move-ItemProperty -Parameter Path

-Path <String[]>
    Specifies the path to the current location of the property. Wildcard
    characters are permitted.

    Required?                    true
    Position?                    0
    Default value                None
    Accept pipeline input?       True (ByPropertyName, ByValue)
    Accept wildcard characters?  true

Pour corriger la commande, nous devons spécifier la destination dans l’applet Move-ItemProperty de commande et utiliser Get-Item pour obtenir le chemin d’accès de l’élément que nous voulons déplacer.

Par exemple,

Get-Item -Path HKLM:\Software\MyCompany\design |
Move-ItemProperty -Destination HKLM:\Software\MyCompany\sales -Name product

Continuation de ligne intrinsèque

Comme nous l’avons déjà vu, un pipeline est une série de commandes connectées par des opérateurs de pipeline (|), généralement écrites sur une seule ligne. Toutefois, pour des fins de lisibilité, PowerShell vous permet de fractionner le pipeline sur plusieurs lignes. Lorsqu’un opérateur de canal est le dernier jeton sur la ligne, l’analyseur PowerShell joint la ligne suivante à la commande actuelle pour poursuivre la construction du pipeline.

Par exemple, le pipeline monoligne suivant :

Command-1 | Command-2 | Command-3

peut être écrit comme suit :

Command-1 |
  Command-2 |
    Command-3

Les espaces de début sur les lignes suivantes ne sont pas significatifs. La mise en retrait améliore la lisibilité.

PowerShell 7 ajoute la prise en charge de la continuation des pipelines avec le caractère de pipeline au début d’une ligne. Les exemples suivants montrent comment utiliser cette nouvelle fonctionnalité.

# Wrapping with a pipe at the beginning of a line (no backtick required)
Get-Process | Where-Object CPU | Where-Object Path
    | Get-Item | Where-Object FullName -match "AppData"
    | Sort-Object FullName -Unique

# Wrapping with a pipe on a line by itself
Get-Process | Where-Object CPU | Where-Object Path
    |
    Get-Item | Where-Object FullName -match "AppData"
    |
    Sort-Object FullName -Unique

Important

Lorsque vous travaillez de manière interactive dans l’interpréteur de commandes, collez du code avec des pipelines au début d’une ligne uniquement lorsque vous utilisez Ctrl+V pour coller. Les opérations de collage avec le bouton droit insèrent les lignes une par une. Étant donné que la ligne ne se termine pas par un caractère de pipeline, PowerShell considère l’entrée comme terminée et exécute cette ligne comme entrée.

Voir aussi