about_Pipelines

간단한 설명

PowerShell에서 파이프라인에 명령 결합

자세한 설명

파이프라인은 파이프라인 연산자()(|ASCII 124)로 연결된 일련의 명령입니다. 각 파이프라인 연산자는 이전 명령의 결과를 다음 명령으로 보냅니다.

첫 번째 명령의 출력은 두 번째 명령에 대한 입력으로 처리하기 위해 보낼 수 있습니다. 그리고 그 출력은 또 다른 명령으로 보낼 수 있습니다. 그 결과 일련의 간단한 명령으로 구성된 복잡한 명령 체인 또는 파이프라인 이 생성됩니다.

예를 들면 다음과 같습니다.

Command-1 | Command-2 | Command-3

이 예제에서는 내보내는 개체가 Command-1 .으로 Command-2전송됩니다. Command-2 는 개체를 처리하고 으로 Command-3보냅니다. Command-3 는 개체를 처리하고 파이프라인 아래로 보냅니다. 파이프라인에 더 이상 명령이 없으므로 결과가 콘솔에 표시됩니다.

파이프라인에서 명령은 왼쪽에서 오른쪽으로 순서대로 처리됩니다. 처리는 단일 작업으로 처리되고 출력이 생성될 때 표시됩니다.

다음은 간단한 예입니다. 다음 명령은 메모장 프로세스를 가져오고 중지합니다.

예를 들면 다음과 같습니다.

Get-Process notepad | Stop-Process

첫 번째 명령은 cmdlet을 Get-Process 사용하여 메모장 프로세스를 나타내는 개체를 가져옵니다. 파이프라인 연산자(|)를 사용하여 프로세스 개체를 cmdlet으로 Stop-Process 보내 메모장 프로세스를 중지합니다. Stop-Process 지정된 프로세스가 파이프라인을 통해 제출되기 때문에 명령에 프로세스를 지정하는 Name 또는 ID 매개 변수가 없습니다.

이 파이프라인 예제에서는 현재 디렉터리의 텍스트 파일을 가져오고, 길이가 10,000바이트를 초과하는 파일만 선택하고, 길이별로 정렬하고, 표에 있는 각 파일의 이름과 길이를 표시합니다.

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

이 파이프라인은 지정된 순서로 네 개의 명령으로 구성됩니다. 다음 그림에서는 파이프라인의 다음 명령으로 전달되는 각 명령의 출력을 보여 줍니다.

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

파이프라인 사용

대부분의 PowerShell cmdlet은 파이프라인을 지원하도록 설계되었습니다. 대부분의 경우 Get cmdlet의 결과를 동일한 명사로 다른 cmdlet으로 파이프할 수 있습니다. 예를 들어 cmdlet의 출력을 Get-Service 또는 Stop-Service cmdlet으로 Start-Service 파이프할 수 있습니다.

이 예제 파이프라인은 컴퓨터에서 WMI 서비스를 시작합니다.

Get-Service wmi | Start-Service

또 다른 예로 PowerShell 레지스트리 공급자의 Get-Item 출력을 Get-ChildItem cmdlet으로 파이프할 New-ItemProperty 수 있습니다. 다음은 새 레지스트리 항목인 NoOfEmployees(값 이 8124)를 MyCompany 레지스트리 키에 추가하는 예제입니다 .

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

와 같은 Get-MemberGroup-ObjectWhere-ObjectSort-ObjectMeasure-Object 유틸리티 cmdlet의 대부분은 파이프라인에서 거의 독점적으로 사용됩니다. 모든 개체 형식을 이러한 cmdlet으로 파이프할 수 있습니다. 이 예제에서는 각 프로세스의 열린 핸들 수를 기준으로 컴퓨터의 모든 프로세스를 정렬하는 방법을 보여 줍니다.

Get-Process | Sort-Object -Property handles

개체를 서식 지정, 내보내기 및 출력 cmdlet(예: , Format-Table, Export-ClixmlExport-CSVOut-File.)으로 Format-List파이프할 수 있습니다.

이 예제에서는 cmdlet을 Format-List 사용하여 프로세스 개체의 속성 목록을 표시하는 방법을 보여줍니다.

Get-Process winlogon | Format-List -Property *

네이티브 명령의 출력을 PowerShell cmdlet으로 파이프할 수도 있습니다. 예시:

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

성공오류 스트림은 다른 셸의 stdin 및 stderr 스트림과 유사합니다. 그러나 stdin은 입력을 위해 PowerShell 파이프라인에 연결되지 않습니다. 자세한 내용은 about_Redirection 참조하세요.

간단한 명령을 파이프라인에 결합하면 시간과 입력이 절약되고 스크립팅의 효율성이 높아집니다.

파이프라인 작동 방식

이 섹션에서는 입력 개체가 cmdlet 매개 변수에 바인딩되고 파이프라인 실행 중에 처리되는 방법을 설명합니다.

파이프라인 입력 허용

파이프라닝을 지원하려면 수신 cmdlet에 파이프라인 입력을 허용하는 매개 변수가 있어야 합니다. Get-Help 전체 또는 매개 변수 옵션과 함께 명령을 사용하여 cmdlet의 매개 변수가 파이프라인 입력을 수락하는지 확인합니다.

예를 들어 cmdlet의 매개 변수 중 파이프라인 입력을 Start-Service 허용하는 매개 변수를 확인하려면 다음을 입력합니다.

Get-Help Start-Service -Full

또는

Get-Help Start-Service -Parameter *

cmdlet에 Start-Service 대한 도움말은 InputObjectName 매개 변수만 파이프라인 입력을 허용한다는 것을 보여줍니다.

-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

파이프라인을 통해 개체를 Start-Service보내면 PowerShell은 개체를 InputObject 및 Name 매개 변수와 연결하려고 시도합니다.

파이프라인 입력을 수락하는 방법

Cmdlet 매개 변수는 다음 두 가지 방법 중 하나로 파이프라인 입력을 수락할 수 있습니다.

  • ByValue: 매개 변수는 예상된 .NET 형식과 일치하거나 해당 형식으로 변환할 수 있는 값을 허용합니다.

    예를 들어 Name 매개 변수는 Start-Service 값별로 파이프라인 입력을 허용합니다. 문자열로 변환할 수 있는 문자열 개체 또는 개체를 허용할 수 있습니다.

  • ByPropertyName: 매개 변수는 입력 개체에 매개 변수와 이름이 같은 속성이 있는 경우에만 입력을 허용합니다.

    예를 들어 Name 매개 변수는 Start-Service Name 속성이 있는 개체를 허용할 수 있습니다. 개체의 속성을 나열하려면 개체에 파이프합니다 Get-Member.

일부 매개 변수는 값 또는 속성 이름 둘 다로 개체를 수락할 수 있으므로 파이프라인에서 입력을 쉽게 수행할 수 있습니다.

매개 변수 바인딩

한 명령에서 다른 명령으로 개체를 파이프하는 경우 PowerShell은 파이프된 개체를 수신 cmdlet의 매개 변수와 연결하려고 시도합니다.

PowerShell의 매개 변수 바인딩 구성 요소는 다음 조건에 따라 입력 개체를 cmdlet 매개 변수와 연결합니다.

  • 매개 변수는 파이프라인의 입력을 수락해야 합니다.
  • 매개 변수는 전송되는 개체의 형식 또는 예상 형식으로 변환할 수 있는 형식을 허용해야 합니다.
  • 매개 변수가 명령에 사용되지 않았습니다.

예를 들어 Start-Service cmdlet에는 많은 매개 변수가 있지만 그 중 두 개의 매개 변수인 NameInputObject 는 파이프라인 입력을 허용합니다. Name 매개 변수는 문자열을 사용하고 InputObject 매개 변수는 서비스 개체를 사용합니다. 따라서 문자열, 서비스 개체 및 문자열 또는 서비스 개체로 변환할 수 있는 속성을 사용하여 개체를 파이프할 수 있습니다.

PowerShell은 가능한 한 효율적으로 매개 변수 바인딩을 관리합니다. PowerShell이 특정 매개 변수에 바인딩되도록 제안하거나 강제 적용할 수는 없습니다. PowerShell이 파이프된 개체를 바인딩할 수 없는 경우 명령이 실패합니다.

바인딩 오류 문제 해결에 대한 자세한 내용은 이 문서의 뒷부분에 있는 파이프라인 오류 조사를 참조하세요.

일회성 처리

명령에 개체를 파이핑하는 것은 명령의 매개 변수를 사용하여 개체를 제출하는 것과 비슷합니다. 파이프라인 예제를 살펴보겠습니다. 이 예제에서는 파이프라인을 사용하여 서비스 개체 테이블을 표시합니다.

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

기능적으로 이는 개체 컬렉션을 제출하는 InputObject 매개 변수 Format-Table 를 사용하는 것과 같습니다.

예를 들어 InputObject 매개 변수를 사용하여 전달되는 변수에 서비스 컬렉션을 저장할 수 있습니다.

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

또는 InputObject 매개 변수에 명령을 포함할 수 있습니다.

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

그러나 중요한 차이점이 있습니다. 여러 개체를 명령에 파이프하는 경우 PowerShell은 한 번에 하나씩 명령으로 개체를 보냅니다. 명령 매개 변수를 사용하면 개체가 단일 배열 개체로 전송됩니다. 이 사소한 차이는 중대한 결과를 초래합니다.

파이프라인을 실행할 때 PowerShell은 인터페이스 또는 제네릭 대응을 구현하는 모든 형식을 IEnumerable 자동으로 열거합니다. 열거된 항목은 파이프라인을 통해 한 번에 하나씩 전송됩니다. 또한 PowerShell은 속성을 통해 System.Data.DataTable 형식을 Rows 열거합니다.

자동 열거형에는 몇 가지 예외가 있습니다.

  • 해시 테이블, 인터페이스 또는 해당 제네릭 테이블을 구현 IDictionary 하는 형식 및 System.Xml.XmlNode 형식에 대한 메서드를 호출 GetEnumerator() 해야 합니다.
  • System.String 클래스는 구현되지만 IEnumerablePowerShell은 문자열 개체를 열거하지 않습니다.

다음 예제에서는 배열 및 해시 테이블을 cmdlet에 파이프하여 Measure-Object 파이프라인에서 받은 개체 수를 계산합니다. 배열에는 여러 멤버가 있고 해시 테이블은 여러 키-값 쌍을 가합니다. 배열만 한 번에 하나씩 열거됩니다.

@(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 :

마찬가지로 cmdlet에서 Get-Process cmdlet으로 여러 프로세스 개체를 파이프하는 Get-Member 경우 PowerShell은 각 프로세스 개체를 한 번에 Get-Member하나씩 보냅니다. Get-Member 는 프로세스 개체의 .NET 클래스(형식)와 해당 속성 및 메서드를 표시합니다.

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

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

참고 항목

Get-Member 는 중복을 제거하므로 개체가 모두 동일한 형식인 경우 하나의 개체 형식만 표시합니다.

그러나 InputObject 매개 변수를 Get-MemberGet-Member사용하는 경우 System.Diagnostics.Process 개체의 배열을 단일 단위로 받습니다. 개체 배열의 속성을 표시합니다. System.Object 형식 이름 뒤의 배열 기호([])를 확인합니다.

예를 들면 다음과 같습니다.

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()
...

이 결과는 의도한 결과가 아닐 수 있습니다. 그러나 이해한 후에는 사용할 수 있습니다. 예를 들어 모든 배열 개체에는 Count 속성이 있습니다. 이를 사용하여 컴퓨터에서 실행 중인 프로세스 수를 계산할 수 있습니다.

예를 들면 다음과 같습니다.

(Get-Process).count

파이프라인 아래로 전송된 개체는 한 번에 하나씩 배달된다는 점을 기억해야 합니다.

파이프라인에서 네이티브 명령 사용

PowerShell을 사용하면 파이프라인에 네이티브 외부 명령을 포함할 수 있습니다. 그러나 PowerShell의 파이프라인은 개체 지향적이며 원시 바이트 데이터를 지원하지 않는다는 점에 유의해야 합니다.

원시 바이트 데이터를 출력하는 네이티브 프로그램에서 출력을 파이핑하거나 리디렉션하면 출력이 .NET 문자열로 변환됩니다. 이 변환으로 인해 원시 데이터 출력이 손상될 수 있습니다.

그러나 PowerShell 7.4는 네이티브 명령의 stdout 스트림을 파일로 리디렉션하거나 바이트 스트림 데이터를 네이티브 명령의 stdin 스트림으로 파이핑할 때 바이트 스트림 데이터를 유지하는 실험적 기능을 추가 PSNativeCommandPreserveBytePipe 했습니다.

예를 들어 네이티브 명령을 curl 사용하여 이진 파일을 다운로드하고 리디렉션을 사용하여 디스크에 저장할 수 있습니다.

$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

바이트 스트림 데이터를 다른 네이티브 명령의 stdin 스트림으로 파이프할 수도 있습니다. 다음 예제에서는 을 사용하여 curl압축된 TAR 파일을 다운로드합니다. 다운로드한 파일 데이터는 보관 파일의 tar 내용을 추출하기 위해 명령으로 스트리밍됩니다.

# native command output piped to a native command
curl -s -L $uri | tar -xzvf - -C .

PowerShell 명령의 바이트 스트림 출력을 네이티브 명령의 입력으로 파이프할 수도 있습니다. 다음 예제에서는 이전 예제와 동일한 TAR 파일을 다운로드하는 데 사용합니다 Invoke-WebRequest .

# 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 .

이 기능은 stderr 출력을 stdout으로 리디렉션할 때 바이트 스트림 데이터를 지원하지 않습니다. stderrstdout 스트림을 결합하면 결합된 스트림이 문자열 데이터로 처리됩니다.

파이프라인 오류 조사

PowerShell이 파이프된 개체를 수신 cmdlet의 매개 변수와 연결할 수 없으면 명령이 실패합니다.

다음 예제에서는 레지스트리 항목을 한 레지스트리 키에서 다른 레지스트리 키로 이동하려고 합니다. cmdlet은 Get-Item 대상 경로를 가져오고 cmdlet에 Move-ItemProperty 파이프됩니다. 이 Move-ItemProperty 명령은 이동할 레지스트리 항목의 현재 경로와 이름을 지정합니다.

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

명령이 실패하고 PowerShell에서 다음 오류 메시지를 표시합니다.

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

조사하려면 cmdlet을 Trace-Command 사용하여 PowerShell의 매개 변수 바인딩 구성 요소를 추적합니다. 다음 예제에서는 파이프라인이 실행되는 동안 매개 변수 바인딩을 추적합니다. PSHost 매개 변수는 콘솔에 추적 결과를 표시하고 FilePath 매개 변수는 나중에 참조하기 위해 추적 결과를 파일로 debug.txt 보냅니다.

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
}

추적 결과는 길지만 cmdlet에 바인딩된 값과 cmdlet에 Get-Item 바인딩 Move-ItemProperty 되는 명명된 값을 표시합니다.

...
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`]
...

마지막으로 실패한 대상 매개 변수 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
...

대상 매개 변수의 Get-Help 특성을 보려면 cmdlet을 사용합니다.

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

결과에 따르면 대상 은 파이프라인 입력만 "속성 이름별"으로 사용합니다. 따라서 파이프된 개체에는 Destination이라는 속성이 있어야 합니다.

에서 오는 Get-Item개체의 속성을 확인하는 데 사용합니다Get-Member.

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

출력은 항목이 Destination 속성이 없는 Microsoft.Win32.RegistryKey 개체임을 보여줍니다. 명령이 실패한 이유를 설명합니다.

Path 매개 변수는 이름 또는 값별로 파이프라인 입력을 허용합니다.

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

명령을 수정하려면 cmdlet에서 대상을 Move-ItemProperty 지정하고 이동하려는 항목의 경로를 가져오는 데 사용해야 Get-Item 합니다.

예를 들면 다음과 같습니다.

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

내장 선 연속

이미 설명한 것처럼 파이프라인은 일반적으로 한 줄로 작성된 파이프라인 연산자()|로 연결된 일련의 명령입니다. 그러나 가독성을 위해 PowerShell을 사용하면 파이프라인을 여러 줄로 분할할 수 있습니다. 파이프 연산자가 줄의 마지막 토큰인 경우 PowerShell 파서는 다음 줄을 현재 명령에 조인하여 파이프라인의 생성을 계속합니다.

예를 들어 다음 단일 줄 파이프라인은 다음과 같습니다.

Command-1 | Command-2 | Command-3

은 다음과 같이 작성할 수 있습니다.

Command-1 |
    Command-2 |
    Command-3

후속 줄의 선행 공백은 중요하지 않습니다. 들여쓰기를 통해 가독성이 향상됩니다.

PowerShell 7은 줄의 시작 부분에 파이프라인 문자를 사용하여 파이프라인의 연속을 지원합니다. 다음 예제에서는 이 새 기능을 사용하는 방법을 보여 줍니다.

# 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

셸에서 대화형으로 작업하는 경우 Ctrl+V를 사용하여 붙여넣을 때만 선의 시작 부분에 파이프라인을 사용하여 코드를 붙여넣습니다. 붙여넣기 작업을 마우스 오른쪽 단추로 클릭하여 한 번에 하나씩 줄을 삽입합니다. 줄이 파이프라인 문자로 끝나지 않으므로 PowerShell은 입력이 완료된 것으로 간주하고 입력된 대로 해당 줄을 실행합니다.

참고 항목