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 les 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 le traitement en tant qu’entrée à la deuxième commande. Et cette sortie peut être envoyée à une autre commande. Le résultat est une chaîne de commandes 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 émis Command-1
sont envoyés à Command-2
.
Command-2
traite les objets et les envoie à Command-3
. Command-3
traite les objets et les envoie vers le bas du pipeline. Étant donné qu’il n’y a plus de commandes dans le pipeline, les résultats sont affichés sur la console.
Dans un pipeline, les commandes sont traitées dans l’ordre de gauche à droite. Le traitement est géré en tant qu’opération unique et la sortie s’affiche à mesure qu’elle est générée.
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 qui sont de plus de 10 000 octets, les trie par longueur et affiche le nom et la longueur de chaque fichier d’une table.
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
les applets de commande.
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 du fournisseur de Registre PowerShell vers Get-ChildItem
l’applet New-ItemProperty
de Get-Item
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-Object
, , Group-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-Clixml
, Export-CSV
, et 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 permet de gagner du temps et de taper, ce qui 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 quels paramètres d’une applet de commande acceptent l’entrée de pipeline.
Par exemple, pour déterminer quels paramètres de l’applet Start-Service
de commande acceptent l’entrée de pipeline, tapez :
Get-Help Start-Service -Full
or
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 des applets 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 d’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
Start-Service
peut accepter des objets qui ont une propriété Name . Pour répertorier les propriétés d’un objet, dirigez-le versGet-Member
.
Certains paramètres peuvent accepter des objets par valeur ou par nom de propriété, ce qui facilite la prise en charge de l’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 prend des chaînes et le paramètre InputObject prend des 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 PowerShell à établir une liaison à 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 à usage unique
Les objets de piping vers une commande ressemblent beaucoup à 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
Fonctionnellement, il s’agit de l’utilisation du paramètre InputObject de l’envoi de Format-Table
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 une par une. 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 significatives.
Lors de l’exécution d’un pipeline, PowerShell énumère automatiquement tout type qui implémente l’interface IEnumerable
ou son équivalent générique. Les éléments énumérés sont envoyés via le pipeline un par un. PowerShell énumère également les types System.Data.DataTable via la Rows
propriété.
Il existe quelques exceptions à l’énumération automatique.
- Vous devez appeler la méthode pour les
GetEnumerator()
tables de hachage, les types qui implémentent l’interfaceIDictionary
ou son équivalent générique et les types System.Xml.XmlNode . - La classe System.String implémente
IEnumerable
, mais PowerShell n’énumère pas les objets de chaîne.
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 à partir du pipeline. Le tableau a plusieurs membres et la table de hachage a plusieurs paires clé-valeur. Seul le tableau est énuméré un à la fois.
@(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 à la fois, à 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
...
Remarque
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 du 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 peut ne pas être ce que vous avez prévu. Mais après avoir 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 vers le bas du 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 d’octet brutes.
Le piping ou la redirection de sortie à partir d’un programme natif qui génère des données d’octet brutes convertit la sortie en chaînes .NET. Cette conversion peut entraîner une altération de la sortie de données brutes.
Toutefois, PowerShell 7.4 a ajouté la fonctionnalité expérimentale qui préserve les données de flux d’octets lors de la redirection du flux stdout d’une commande native vers un fichier ou lors de la PSNativeCommandPreserveBytePipe
redirection des données de flux d’octets vers le flux stdin d’une commande native.
Par exemple, à l’aide de la commande native curl
, vous pouvez télécharger un fichier binaire et l’enregistrer sur le disque à l’aide de la redirection.
$uri = 'https://github.com/PowerShell/PowerShell/releases/download/v7.3.4/powershell-7.3.4-linux-arm64.tar.gz'
# native command redirected to a file
curl -s -L $uri > powershell.tar.gz
Vous pouvez également diriger les données de flux d’octets vers le flux stdin d’une autre commande native. L’exemple suivant télécharge un fichier TAR compressé à l’aide de curl
. Les données du fichier téléchargé sont diffusées en continu vers la commande tar
pour extraire le contenu de l’archive.
# native command output piped to a native command
curl -s -L $uri | tar -xzvf - -C .
Vous pouvez également diriger la sortie de flux d’octets d’une commande PowerShell vers l’entrée de la commande native. Les exemples suivants utilisent Invoke-WebRequest
pour télécharger le même fichier TAR que l’exemple précédent.
# byte stream piped to a native command
(Invoke-WebRequest $uri).Content | tar -xzvf - -C .
# bytes piped to a native command (all at once as byte[])
,(Invoke-WebRequest $uri).Content | tar -xzvf - -C .
Cette fonctionnalité ne prend pas en charge les données de flux d’octets lors de la redirection de la sortie stderr vers stdout. Lorsque vous combinez les flux stderr et stdout, les flux combinés sont traités comme des données de chaîne.
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 examiner, utilisez l’applet Trace-Command
de commande pour suivre le composant de liaison de paramètre 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 envoient les résultats de la trace au debug.txt
fichier pour 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 affichent 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 d’échec Move-ItemProperty
.
...
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 la 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.
Permet Get-Member
de voir les propriétés de l’objet provenant Get-Item
de .
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 l’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 indiqué précédemment, un pipeline est une série de commandes connectées par les opérateurs de pipeline (|
), généralement écrites sur une seule ligne. Toutefois, pour une 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 continuer la construction du pipeline.
Par exemple, le pipeline à ligne unique 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 à la fois. Étant donné que la ligne ne se termine pas par un caractère de pipeline, PowerShell considère que l’entrée est terminée et exécute cette ligne comme entrée.