about_ForEach

업데이트 날짜: 2014년 5월

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

항목

about_Foreach

간단한 설명

항목 컬렉션의 모든 항목을 이동하는 데 사용할 수 있는 언어 명령을 설명합니다.

자세한 설명

Foreach 루프라고도 하는 Foreach 문은 항목 컬렉션에서 일련의 값을 단계별로 실행(반복)하기 위한 언어 구문입니다.

이동할 컬렉션의 가장 간단하고 가장 일반적인 형식은 배열입니다. Foreach 루프 내에서는 일반적으로 배열의 각 항목에 대해 하나 이상의 명령을 실행합니다.

구문

ForEach 구문은 다음과 같습니다.

          foreach ($<item> in $<collection>){<statement list>}

간단한 구문

Windows PowerShell® 3.0부터 Where 및 ForEach 등의 언어 키워드가 포함된 구문이 간소화되었습니다. 컬렉션의 멤버에서 작동하는 비교 연산은 매개 변수로 처리됩니다. 메서드를 스크립트 블록에 포함하거나 자동 변수 "$_."를 추가하지 않고 컬렉션의 멤버에서 메서드를 사용할 수 있습니다. 다음 두 가지 예제를 고려합니다.

          dir cert:\ -Recurse | foreach GetKeyAlgorithm
          dir cert:\ -Recurse | foreach {$_.GetKeyAlgorithm()}

두 명령이 모두 작동하지만 첫 번째 명령은 스크립트 블록이나 $_. 자동 변수를 사용하지 않고 결과를 반환합니다. GetKeyAlgorithm 메서드는 ForEach의 매개 변수로 처리됩니다. 첫 번째 명령은 같은 결과를 반환하지만 오류가 없습니다. 이는 간단한 구문은 지정된 인수가 적용되지 않는 항목에 대한 결과를 반환하려고 시도하지 않기 때문입니다.

이 예제에서 Get-Process 속성 Description은 ForEach 문의 매개 변수 인수로 전달됩니다. 결과는 활성 프로세스에 대한 설명입니다.

          Get-Process | ForEach Description

명령 파이프라인 외부의 Foreach 문

괄호로 묶인 Foreach 문 부분은 반복할 변수 및 컬렉션을 나타냅니다. Windows PowerShell에서는 Foreach 루프가 실행될 때 변수($<item>)를 자동으로 만듭니다. 루프를 통해 각 반복 전에 변수가 컬렉션의 값으로 설정됩니다. Foreach 문 뒤의 블록 {<statement list>}에는 컬렉션의 각 항목에 대해 실행할 명령 집합이 포함됩니다.

예제

예를 들어 다음 예제의 Foreach 루프는 값을 $letterArray 배열로 표시합니다.

        
          $letterArray = "a","b","c","d"
          foreach ($letter in $letterArray)
          {
              Write-Host $letter
          }

이 예제에서 $letterArray 배열은 문자열 값 "a", "b", "c", "d"를 사용하여 만들어지고 초기화됩니다. Foreach 문이 처음 실행될 때 이 문은 $letter 변수를 $letterArray의 첫 번째 항목("a")과 같게 설정합니다. 그다음에 Write-Host cmdlet을 사용하여 문자 a를 표시합니다. 다음에 루프를 통해 $letter가 "b"로 설정됩니다. Foreach 루프가 문자 d를 표시한 후 Windows PowerShell가 루프를 종료합니다.

Windows PowerShell 명령 프롬프트에서 전체 Foreach 문을 명령으로 실행하려면 이 문이 한 줄에 표시되어야 합니다. 명령을 .ps1 스크립트 파일에 배치하면 전체 Foreach 문이 한 줄에 표시될 필요가 없습니다.

Foreach 문은 항목 컬렉션을 반환하는 cmdlet과 함께 사용될 수도 있습니다. 다음 예제에서 Foreach 문은 Get-ChildItem cmdlet에서 반환되는 항목 목록을 단계별로 실행합니다.

          foreach ($file in Get-ChildItem)
          {
              Write-Host $file
          }

If 문을 사용하여 반환되는 결과를 제한하는 방식으로 예제를 구체화할 수 있습니다. 다음 예제에서 Foreach 문은 이전 예제와 같은 루핑 작업을 수행하지만 If 문을 추가하여 100KB(킬로바이트)보다 큰 파일로 결과를 제한합니다.

          foreach ($file in Get-ChildItem)
          {
              if ($file.length -gt 100KB) 
              {
                  Write-Host $file
              }
          }

이 예제에서 Foreach 루프는 $file 변수 속성을 사용하여 비교 작업을 수행합니다($file.length -gt 100KB). $file 변수는 Get-ChildItem cmdlet에서 반환되는 개체에 모든 속성을 포함합니다. 따라서 파일 이름 이상의 결과를 반환할 수 있습니다. 다음 예제에서 Windows PowerShell은 문 목록 내부에 길이 및 마지막 액세스 시간을 반환합니다.

          foreach ($file in Get-ChildItem)
          {
              if ($file.length -gt 100KB) 
              {
                  Write-Host $file
                  Write-Host $file.length
                  Write-Host $file.lastaccesstime
              }
          }

이 예제에서는 문 목록의 단일 명령을 실행하도록 제한되지 않습니다.

Foreach 루프 내부에서 변수를 사용하고 루프 내부에서 변수를 증분할 수도 있습니다. 다음 예제에서는 크기 100KB를 초과하는 파일 수를 계산합니다.

          $i = 0
          foreach ($file in Get-ChildItem)
          {
              if ($file.length -gt 100KB) 
              {
                  Write-Host $file "file size:" ($file.length / 
          1024).ToString("F0") KB
                  $i = $i + 1
              }
          }
          if ($i -ne 0)
          {
              Write-Host
              Write-Host $i " file(s) over 100 KB in the current 
          directory."}
          else 
          {
              Write-Host "No files greater than 100 KB in the current 
          directory."
          }

이전 예제에서 $i 변수는 루프 외부에서 0으로 설정되고 변수는 100KB보다 큰 것으로 확인된 각 파일에 대한 루프 내부에서 증분됩니다. 루프가 있으면 If 문은 $i 값을 평가하여 100KB보다 큰 모든 파일의 수를 표시합니다. 또는 100KB를 초과하는 파일이 없음을 나타내는 메시지를 표시합니다.

이전 예제에서는 파일 길이 결과의 형식을 지정하는 방법을 보여 줍니다.

          ($file.length / 1024).ToString("F0")

값을 1,024로 나누어서 결과는 바이트가 아닌 킬로바이트로 표시되고 결과 값은 결과에서 소수 값을 제거하도록 고정 소수점 형식 지정자를 사용하여 형식이 지정됩니다. 0을 사용하면 형식 지정자가 소수 자릿수를 표시하지 않습니다.

명령 파이프라인 내부의 Foreach 문

Foreach가 명령 파이프라인에 나타나면 Windows PowerShell에서는 ForEach-Object 명령을 호출하는 foreach 별칭을 사용합니다. 명령 파이프라인에서 foreach 별칭을 사용하면 Foreach 문을 사용할 때 ($<item> in $<collection>) 구문을 포함하지 않습니다. 이는 파이프라인의 이전 명령이 이 정보를 제공하기 때문입니다. 명령 파이프라인에서 사용될 때 foreach 별칭 구문은 다음과 같습니다.

          <command> | foreach {<command_block>}

예를 들어 loop 다음 명령의 Foreach 루프는 작업 집합(메모리 사용)이 20MB(메가바이트)보다 큰 프로세스를 표시합니다.

Get-Process 명령은 컴퓨터의 모든 프로세스를 가져옵니다. Foreach 별칭은 각 프로세스에 대한 스크립트 블록에서 명령을 순서대로 수행합니다.

IF 문은 작업 집합(WS)이 20MB보다 큰 프로세스를 선택합니다. Write-Host cmdlet은 프로세스 이름을 쓰고 그 뒤에 콜론을 추가합니다. 바이트로 저장되는 작업 집합 값을 1MB로 나누어서 작업 집합 값을 MB 단위로 가져옵니다. 그다음에 결과를 double에서 string으로 변환합니다. 이 cmdlet은 0 소수(F0), 공백 구분 기호(" "), "MB" 순으로 포함된 고정 소수점 수로 값을 표시합니다.

          Write-Host "Processes with working sets greater than 20 MB."
          Get-Process | foreach { 
             if ($_.WS -gt 20MB)
             { Write-Host $_.name ": " ($_.WS/1MB).ToString("F0") MB -Separator ""}
          }

foreach 별칭은 시작 명령 블록, 중간 명령 블록 및 종료 끝 블록을 지원합니다. 시작 및 끝 명령 블록은 한 번 실행되고 중간 명령 블록은 Foreach 루프가 컬렉션이나 배열을 단계별로 실행할 때마다 실행됩니다.

명령 파이프라인에서 명령 블록의 시작, 중간 및 끝 집합과 함께 사용될 때 foreach 별칭 구문은 다음과 같습니다.

          <command> | foreach {<beginning command_block>}{<middle 
          command_block>}{<ending command_block>}

다음 예제에서는 시작, 중간 및 끝 명령 블록의 사용을 보여 줍니다.

          Get-ChildItem | foreach {
          $fileCount = $directoryCount = 0}{
          if ($_.PsIsContainer) {$directoryCount++} else {$fileCount++}}{
          "$directoryCount directories and $fileCount files"}

시작 블록은 두 변수를 만들고 0으로 초기화합니다.

          {$fileCount = $directoryCount = 0}

중간 블록은 Get-ChildItem에서 반환되는 각 항목이 디렉터리 또는 파일인지를 평가합니다.

          {if ($_.PsIsContainer) {$directoryCount++} else {$fileCount++}}

반환되는 항목이 디렉터리이면 $directoryCount 변수가 1씩 증분됩니다. 항목이 디렉터리가 아니면 $fileCount 변수가 1식 증분됩니다. 끝 블록은 중간 블록이 루핑 작업을 완료한 후 실행되고 작업 결과를 반환합니다.

          {"$directoryCount directories and $fileCount files"}

시작, 중간 및 끝 명령 블록 구조와 파이프라인 연산자를 사용하여 이전 예제를 다시 작성하고 다음과 같이 100KB보다 큰 파일을 찾습니다.

          Get-ChildItem | foreach{
              $i = 0}{
              if ($_.length -gt 100KB)
              {
                  Write-Host $_.name "file size:" ($_.length / 
          1024).ToString("F0") KB
                  $i++
              }
              }{
              if ($i -ne 0)
              {
                  Write-Host
                  Write-Host "$i file(s) over 100 KB in the current 
          directory."
              }
              else 
              {
              Write-Host "No files greater than 100 KB in the current 
          directory."}
              }

스크립트와 스크립트 모듈에서 사용되는 함수를 반환하는 다음 함수 예제에서는 함수 이름을 선언하기 위해 여러 줄에 걸쳐 있고 간격이 비정상적이거나 일관되지 않은 함수가 있더라도, For 루프에서 "skip X"와 비슷하게 작동하는 MoveNext 메서드 및 foreach 스크립트 블록 내부에서 $foreach 변수의 Current 속성을 사용하는 방법을 보여 줍니다. 스크립트나 스크립트 모듈에서 사용되는 함수에 주석이 있을 경우에도 예제가 작동합니다.

         function Get-FunctionPosition {
             [CmdletBinding()]
             [OutputType('FunctionPosition')]
             param(
                 [Parameter(Position=0, Mandatory, ValueFromPipeline, ValueFromPipelineByPropertyName)]
                 [ValidateNotNullOrEmpty()]
                 [Alias('PSPath')]
                 [System.String[]]
                 $Path
             )
             process {
                 try {
                     $filesToProcess = if ($_ -is [System.IO.FileSystemInfo]) {
                         $_
                     } else {
                         Get-Item -Path $Path
                     }
                     foreach ($item in $filesToProcess) {
                         if ($item.PSIsContainer -or $item.Extension -notin @('.ps1','.psm1')) {
                             continue
                         }
                         $tokens = $errors = $null
                         $ast = [System.Management.Automation.Language.Parser]::ParseFile($item.FullName,([REF]$tokens),([REF]$errors))
                         if ($errors) {
                             Write-Warning "File '$($item.FullName)' has $($errors.Count) parser errors."
                         }
                         :tokenLoop foreach ($token in $tokens) {
                             if ($token.Kind -ne 'Function') {
                                 continue
                             }
                             $position = $token.Extent.StartLineNumber
                             do {
                                 if (-not $foreach.MoveNext()) {
                                     break tokenLoop
                                 }
                                 $token = $foreach.Current
                             } until ($token.Kind -in @('Generic','Identifier'))
                             $functionPosition = [pscustomobject]@{
                                       Name = $token.Text
                                 LineNumber = $position
                                       Path = $item.FullName
                             }
                             Add-Member -InputObject $functionPosition -TypeName FunctionPosition -PassThru
                         }
                     }
                 } catch {
                     throw
                 }
             }
         }

참고 항목

about_Automatic_Variables

about_If

Foreach-Object