about_Pipelines

업데이트 날짜: 2014년 5월

적용 대상: Windows PowerShell 2.0, Windows PowerShell 3.0, Windows PowerShell 4.0

항목

about_pipelines

간단한 설명

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

자세한 설명

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

파이프라인을 사용하여 한 명령에서 출력된 개체를 처리를 위해 다른 명령의 입력으로 사용하도록 보낼 수 있습니다. 또한 해당 명령의 출력을 다른 명령으로 보낼 수 있습니다. 결과는 매우 강력한 명령 체인 또는 일련의 간단한 명령을 구성되는 "파이프라인"입니다.

예:

Command-1 | Command-2 | Command-3  

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

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

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

         get-process notepad | stop-process

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

다음은 실제 예제입니다. 이 명령 파이프라인은 현재 디렉터리에서 텍스트 파일을 가져오고, 10,000바이트를 초과하는 파일만 선택하고, 길이 기준으로 정렬하고, 각 파일의 이름과 길이를 테이블에 표시합니다.

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

이 파이프라인은 지정된 순서대로 4개의 명령으로 구성됩니다. 이 명령은 가로로 작성되지만 다음 그래픽에서는 프로세스를 세로로 표시합니다.

       Get-ChildItem -path *.txt

                  |
                  |   (FileInfo objects )
                  |   (    .txt         )
                  |
                  V                   

       Where-Object {$_.length -gt 10000}

                  |
                  |   (FileInfo objects )
                  |   (    .txt         )
                  |   ( Length > 10000  )
                  |
                  V

       Sort-Object -property Length

                  |
                  |   (FileInfo objects  )
                  |   (    .txt          )
                  |   ( Length > 10000   )
                  |   ( Sorted by length )
                  |
                  V

       Format-Table -property name, length

                  |   
                  |   (FileInfo objects     )
                  |   (    .txt             )
                  |   ( Length > 10000      )
                  |   ( Sorted by length    )
                  |   (Formatted in a table )
                  |
                  V
        Name                       Length
        ----                       ------
        tmp1.txt                    82920
        tmp2.txt                   114000
        tmp3.txt                   114000

파이프라인 사용

Windows PowerShell cmdlet은 파이프라인에서 사용할 수 있도록 설계되었습니다. 예를 들어 일반적으로 Get cmdlet의 결과를 동일한 동사에 대한 동작 cmdlet(예: Set, Start, Stop 또는 Rename cmdlet)으로 파이프할 수 있습니다.

예를 들어 Get-Service cmdlet에서 Start-Service 또는 Stop-Service cmdlet으로 서비스를 파이프할 수 있습니다(단, 사용하지 않도록 설정한 서비스는 이러한 방식으로 다시 시작할 수 없음).

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

get-service wmi | start-service

Item 및 ItemProperty cmdlet과 같은 Windows PowerShell 공급자의 개체를 가져오고 설정하는 cmdlet 또한 파이프라인에서 사용되도록 설계되었습니다.

예를 들어 Windows PowerShell 레지스트리 공급자의 Get-Item 또는 Get-ChildItem 명령의 결과를 New-ItemProperty cmdlet으로 파이프할 수 있습니다. 이 명령은 MyCompany 레지스트리 키에 값이 8124인 새 레지스트리 항목, NoOfEmployees를 추가합니다.

       get-item -path HKLM:\Software\MyCompany | new-Itemproperty -name NoOfEmployees -value 8124

Get-Member, Where-Object, Sort-Object, Group-Object 및 Measure-Object와 같은 많은 유틸리티 cmdlet은 파이프라인에서 거의 단독으로 사용됩니다. 임의의 개체를 이러한 cmdlet으로 파이프할 수 있습니다.

예를 들어 컴퓨터에 대한 모든 프로세스를 Sort-Object 명령으로 파이프하고 프로세스의 핸들 수에 따라 정렬할 수 있습니다.

get-process | sort-object -property handles

또한 형식 지정 cmdlet(예: Format-List 및 Format-Table), Export cmdlet(예: Export-Clixml 및 Export-CSV), Out cmdlet(예: Out-Printer)으로 개체를 파이프할 수 있습니다.

예를 들어 Winlogon 프로세스를 Format-List cmdlet으로 파이프하여 프로세스의 모든 속성을 목록으로 표시할 수 있습니다.

get-process winlogon | format-list -property *

조금만 작업해보면 간단한 명령을 파이프라인에 결합하여 시간 및 입력 노력을 줄이고 스크립트를 보다 효율적으로 작성할 수 있다는 것을 알 수 있습니다.

파이프라인 작동 방식

개체를 "파이프"하여 한 명령의 출력에 포함된 개체를 다른 명령을 보낼 경우 Windows PowerShell은 파이프된 개체를 수신 cmdlet의 매개 변수 중 하나에 연결하려고 합니다.

이를 위해 입력 개체를 cmdlet 매개 변수에 연결하는 Windows PowerShell "매개 변수 바인딩" 구성 요소는 다음 조건을 충족하는 매개 변수를 찾으려고 합니다.

-- 매개 변수는 파이프라인의 입력을 허용해야 합니다(모두 그런 것은 아님).

-- 매개 변수는 전송되는 개체의 형식이나 개체가 변환될 수 있는 형식을 허용해야 합니다.

-- 매개 변수는 명령에서 아직 사용되고 있지 않아야 합니다.

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

Windows PowerShell의 매개 변수 바인딩 구성 요소가 파이프된 개체를 수신 cmdlet의 매개 변수에 연결할 수 없으면 명령은 실패하고 Windows PowerShell은 누락된 매개 변수 값을 묻는 메시지를 표시합니다.

강제로 매개 변수 바인딩 구성 요소가 파이프된 개체를 특정 매개 변수에 연결하도록 할 수 없으며 매개 변수를 제안할 수도 없습니다. 대신 구성 요소의 논리는 파이핑을 가능한 한 효율적으로 관리합니다.

한 번에 하나씩 처리

개체를 명령에 파이프하는 것은 명령의 매개 변수를 사용하여 개체를 전송하는 것과 매우 비슷합니다.

예를 들어 다음과 같이 컴퓨터의 서비스를 나타내는 개체를 Format-Table 명령에 파이프하는 것은

  get-service | format-table -property name, dependentservices

서비스 개체를 변수에 저장하고 Format-Table의 InputObject 매개 변수를 사용하여 서비스 개체를 전송하는 것이나

  $services = get-service
                  format-table -inputobject $services -property name, dependentservices

매개 변수 값에 명령을 포함시키는 것과 매우 비슷합니다.

                  format-table -inputobject (get-service wmi) -property name, dependentservices

그러나 중요한 차이점이 하나 있습니다. 여러 개체를 하나의 명령에 파이프할 경우 Windows PowerShell은 해당 개체를 한 번에 하나씩 명령으로 보냅니다. 명령 매개 변수를 사용하면 개체가 단일 배열 개체로 전송됩니다.

외견상으로 보이는 이러한 기술적 차이는 흥미로울 수 있으며 경우에 따라 유용한 결과를 가져올 수 있습니다.

예를 들어 Get-Process cmdlet에서 Get-Member cmdlet으로 여러 프로세스 개체를 파이프하는 경우 Windows PowerShell은 한 번에 하나씩 각 프로세스 개체를 Get-Member로 보냅니다. Get-Member는 프로세스 개체의 .NET 클래스(형식) 및 해당 속성과 메서드를 표시합니다. (Get-Member는 중복 항목을 제거하고, 개체가 모두 동일한 형식인 경우 개체 형식을 한 번만 표시합니다.)

이 경우 Get-Member는 각 프로세스 개체(System.Diagnostics.Process 개체)의 속성과 메서드를 표시합니다.

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

이러한 구분은 중요할 수 있으므로 개체를 cmdlet에 파이프할 때는 한 번에 하나씩 전달된다는 점을 기억해둡니다.

파이프라인 입력 허용

파이프라인의 개체를 수신하려면 수신 cmdlet에 파이프라인 입력을 허용하는 매개 변수가 있어야 합니다. Full 또는 Parameter 매개 변수와 함께 Get-Help 명령을 사용하여 cmdlet의 매개 변수 중에서 파이프라인 입력을 허용하는 매개 변수를 확인할 수 있습니다.

Get-Help 기본 표시에서 매개 변수 특성 테이블에 "파이프라인 입력 허용" 항목이 나타납니다. 이 테이블은 Get-Help cmdlet의 Full 또는 Parameter 매개 변수를 사용하는 경우에만 표시됩니다.

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

        get-help start-service -full

        get-help start-service -parameter *

예를 들어 Start-Service cmdlet에 대한 도움말에는 Name 및 InputObject 매개 변수가 파이프라인 입력을 허용한다고 표시됩니다("true"). 다른 모든 매개 변수는 "파이프라인 입력 허용 여부" 행에 "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?                    1
           Default value
      -->  Accept pipeline input?       true (ByValue, ByPropertyName)
           Accept wildcard characters?  true

        -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?                    false
           Position?                    named
           Default value
      -->  Accept pipeline input?       true (ByValue)
           Accept wildcard characters?  false

즉, 파이프라인을 통해 Where-Object cmdlet으로 개체(PsObjects)를 전송할 수 있으며 Windows PowerShell은 해당 개체를 InputObject 매개 변수에 연결합니다.

파이프라인 입력을 허용하는 방법

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

-- ByValue: "값으로"입력을 허용하는 매개 변수는 해당 매개 변수 값과 동일한 .NET 형식을 가진 파이프된 개체 또는 해당 형식으로 변환될 수 있는 개체를 허용할 수 있습니다.

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

-- ByPropertyName: "속성 이름으로"입력을 허용하는 매개 변수는 해당 개체의 속성이 매개 변수와 동일한 이름을 가질 때만 파이프된 개체를 허용할 수 있습니다.

예를 들어 Start-Service의 Name 매개 변수는 Name 속성이 있는 개체를 허용할 수 있습니다.

(개체의 속성을 나열하려면 Get-Member로 파이프합니다.)

일부 매개 변수는 값 또는 속성 이름으로 개체를 허용할 수 있습니다. 이러한 매개 변수는 파이프라인에서 입력을 쉽게 가져오도록 설계되었습니다.

파이프라인 오류 조사

파이프라인 오류로 인해 명령이 실패하면 오류를 조사하고 명령을 다시 작성할 수 있습니다.

예를 들어 다음 명령은 Get-Item cmdlet을 사용하여 대상 경로를 가져온 다음 경로를 Move-ItemProperty cmdlet으로 파이프하여 한 레지스트리 키에서 다른 레지스트리 키로 레지스트리 항목을 이동하려고 합니다.

특히, 이 명령은 Get-Item cmdlet을 사용하여 대상 경로를 가져옵니다. 또한 파이프라인 연산자를 사용하여 결과를 Move-ItemProperty cmdlet으로 보냅니다. Move-ItemProperty 명령은 이동할 레지스트리 항목의 현재 경로 및 이름을 지정합니다.

          get-item -path hklm:\software\mycompany\sales | 
          move-itemproperty -path hklm:\software\mycompany\design -name product

이 명령은 실파하고 Windows PowerShell은 다음과 같은 오류 메시지를 표시합니다.

         Move-ItemProperty : The input object cannot be bound to any parameters for the
         command either because the command does not 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 product

오류를 조사하려면 Trace-Command cmdlet을 사용하여 Windows PowerShell의 매개 변수 바인딩 구성 요소를 추적합니다. 다음 명령은 명령이 처리되는 동안 매개 변수 바인딩 구성 요소를 추적합니다. 또한 -pshost 매개 변수를 사용하여 콘솔에 결과를 표시하고 -filepath 명령을 사용하여 나중에 참조할 수 있게 결과를 debug.txt 파일로 보냅니다.

         trace-command -name parameterbinding -expression {get-item -path hklm:\software\mycompany\sales |
             move-itemproperty -path hklm:\software\mycompany\design -name product} -pshost -filepath debug.txt

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

       ... 
        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의 Destination 매개 변수로 경로를 바인딩하려는 시도가 실패했음을 보여 줍니다.

        ...
        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을 사용하여 Destination 매개 변수의 특성을 표시합니다. 다음 명령은 Destination 매개 변수에 대한 자세한 정보를 가져옵니다.

get-help move-itemproperty -parameter destination

결과에는 Destination이 "속성 이름으로"만 파이프라인 입력을 받아들인다는 것이 표시됩니다. 즉, 파이프된 개체에는 Destination이라는 속성이 있어야 합니다.

        -destination <string>
            Specifies the path to the destination location.

            Required?                    true
            Position?                    2
            Default value
            Accept pipeline input?       true (ByPropertyName)
            Accept wildcard characters?  true    

Move-ItemProperty cmdlet으로 파이프되는 개체의 속성을 보려면 Get-Member cmdlet으로 파이프합니다. 다음 명령은 명령의 첫 번째 부분에 대한 결과를 Get-Member cmdlet으로 파이프합니다.

          get-item -path hklm:\software\mycompany\sales | get-member

출력은 해당 항목이 Destination 속성이 없는 Microsoft.Win32.RegistryKey임을 보여 줍니다. 이것이 바로 명령이 실패한 이유입니다.

명령을 해결하려면 Move-ItemProperty cmdlet에 대상을 지정해야 합니다. Get-ItemProperty 명령을 사용하여 경로를 가져올 수 있지만 이름 및 대상을 명령의 Move-ItemProperty 부분에 지정해야 합니다.

         get-item -path hklm:\software\mycompany\design | 
             move-itemproperty -dest hklm:\software\mycompany\design -name product    

명령이 작동하는지 확인하려면 Get-ItemProperty 명령을 사용합니다.

get-itemproperty hklm:\software\mycompany\sales

결과에는 Product 레지스트리 항목이 Sales 키로 이동되었음이 표시됩니다.

        PSPath       : Microsoft.PowerShell.Core\Registry::HKEY_LOCAL_MACHINE\software\mycompany\sales
        PSParentPath : Microsoft.PowerShell.Core\Registry::HKEY_LOCAL_MACHINE\software\mycompany
        PSChildName  : sales
        PSDrive      : HKLM
        PSProvider   : Microsoft.PowerShell.Core\Registry
        Product      : 18

참고 항목

about_objects

about_parameters

about_command_syntax

about_foreach