Powershell은 Bash의 프로세스 대체와 동일합니다.

Powershell은 Bash의 프로세스 대체와 동일합니다.

Bash에는 <(..)프로세스 대체 기능이 있습니다. Powershell과 동등한 것은 무엇입니까?

가 있다는 것을 알고 있지만 $(...)문자열을 반환하고 <(..)외부 명령이 읽을 수 있는 파일을 반환합니다. 이는 예상한 것입니다.

또한 파이프 기반 솔루션을 찾는 것이 아니라 명령줄 중간에 넣을 수 있는 솔루션을 찾고 있습니다.

답변1

이 답변은당신을 위한 것이 아닙니다, 다음과 같은 경우:
- 외부 CLI를 사용해야 하는 경우는 거의 없습니다(일반적으로 노력할 가치가 있습니다. - PowerShell 기본 명령은 함께 사용하면 훨씬 더 잘 작동하며 이러한 기능이 필요하지 않습니다).
- Bash의 프로세스 대체에 익숙하지 않습니다.
이 답변당신을 위한 것입니다, 다음과 같은 경우
- 특히 스크립트를 작성하는 동안 외부 CLI를 자주 사용합니다(습관에서 비롯되었거나 (좋은) PowerShell 기본 대안이 부족하여).
- Bash의 프로세스 대체가 무엇을 할 수 있는지에 익숙하고 감사합니다.
-업데이트: 이제 PowerShell은 Unix 플랫폼에서도 지원되므로 이 기능에 대한 관심이 높아지고 있습니다.GitHub에 대한 이 기능 요청이는 PowerShell이 ​​프로세스 대체와 유사한 기능을 구현함을 의미합니다.

유닉스 세계에서는 Bash/Ksh/Zsh에서프로세스 대체명령 출력을 임시 출력처럼 처리하는 기능을 제공합니다.파일그것은 스스로 정리됩니다. 예를 들어 cat <(echo 'hello'), 여기서는 명령 cat의 출력을 echo다음과 같이 봅니다.임시 파일의 경로함유하는명령 출력.

PowerShell 기본 명령에는 이러한 기능이 실제로 필요하지 않지만 다음 작업을 처리할 때 유용할 수 있습니다.외부 CLI.

PowerShell에서 기능을 에뮬레이션하는 것은 번거롭습니다.하지만 자주 필요하다면 그만한 가치가 있을 수 있습니다.

cf스크립트 블록을 받아들이고, 블록을 실행하고, 그 출력을 임시에 쓰는 함수를 생각해 보세요 . 요청 시 파일이 생성되고 임시 값을 반환합니다. 파일의 경로; 예:

 findstr.exe "Windows" (cf { Get-ChildItem c:\ }) # findstr sees the temp. file's path.

이것은 설명하지 않은 간단한 예입니다.필요그런 기능에 대해서는 글쎄요. 아마도 더 설득력 있는 시나리오는 다음을 사용하는 것입니다.psftp.exeSFTP 전송의 경우: 일괄(자동) 사용을 위해서는 입력 제공이 필요합니다.파일원하는 명령을 포함하는 반면, 그러한 명령은 즉석에서 문자열로 쉽게 생성될 수 있습니다.

가능한 한 외부 유틸리티와 광범위하게 호환되도록 temp. 파일을 사용해야합니다UTF-8부호화BOM 없이(바이트 순서 표시)가 기본적으로 필요하지만 -BOM필요한 경우 를 사용하여 UTF-8 BOM을 요청할 수 있습니다.

안타깝게도,자동대청소프로세스 대체 측면은 불가능합니다.곧장에뮬레이트되었으므로 명시적인 정리 호출이 필요합니다.; 정리는 호출하여 수행됩니다.cf 인수 없이:

  • 을 위한인터렉티브이용하세요, 당신~할 수 있다prompt다음과 같이 함수 에 정리 호출을 추가하여 정리를 자동화합니다 ( prompt함수는 프롬프트를 반환합니다).$PROMPT_COMMAND, 그러나 Bash의 변수 와 유사하게 프롬프트가 표시될 때마다 비하인드 스토리 명령을 수행하는 데에도 사용할 수 있습니다. 대화형 세션에서 사용할 수 있도록 하려면 cfPowerShell 프로필에 다음과 아래의 정의를 추가하세요 .

    "function prompt { cf 4>`$null; $((get-item function:prompt).definition) }" |
      Invoke-Expression
    
  • 사용하기위한스크립트에서, 정리가 수행되도록 하려면 사용하는 블록 (잠재적으로 전체 스크립트)을 / 블록 cf으로 래핑해야 하며 , 인수 없이 정리를 위해 호출됩니다.tryfinallycf

# Example
try {

  # Pass the output from `Get-ChildItem` via a temporary file.
  findstr.exe "Windows" (cf { Get-ChildItem c:\ })

  # cf() will reuse the existing temp. file for additional invocations.
  # Invoking it without parameters will delete the temp. file.

} finally {
  cf  # Clean up the temp. file.
}

여기에구현: 고급 기능 ConvertTo-TempFile과 간결한 별칭 cf:

메모: PSv3+가 필요한 의 사용은 New-Modulea를 통해 기능을 정의합니다.동적 모듈함수 매개변수와 전달된 스크립트 블록 내에서 참조되는 변수 사이에 변수 충돌이 없는지 확인합니다.

$null = New-Module {  # Load as dynamic module
  # Define a succinct alias.
  set-alias cf ConvertTo-TempFile
  function ConvertTo-TempFile {
    [CmdletBinding(DefaultParameterSetName='Cleanup')]
    param(
        [Parameter(ParameterSetName='Standard', Mandatory=$true, Position=0)]
        [ScriptBlock] $ScriptBlock
      , [Parameter(ParameterSetName='Standard', Position=1)]
        [string] $LiteralPath
      , [Parameter(ParameterSetName='Standard')]
        [string] $Extension
      , [Parameter(ParameterSetName='Standard')]
        [switch] $BOM
    )

    $prevFilePath = Test-Path variable:__cttfFilePath
    if ($PSCmdlet.ParameterSetName -eq 'Cleanup') {
      if ($prevFilePath) { 
        Write-Verbose "Removing temp. file: $__cttfFilePath"
        Remove-Item -ErrorAction SilentlyContinue $__cttfFilePath
        Remove-Variable -Scope Script  __cttfFilePath
      } else {
        Write-Verbose "Nothing to clean up."
      }
    } else { # script block specified
      if ($Extension -and $Extension -notlike '.*') { $Extension = ".$Extension" }
      if ($LiteralPath) {
        # Since we'll be using a .NET framework classes directly, 
        # we must sync .NET's notion of the current dir. with PowerShell's.
        [Environment]::CurrentDirectory = $pwd
        if ([System.IO.Directory]::Exists($LiteralPath)) { 
          $script:__cttfFilePath = [IO.Path]::Combine($LiteralPath, [IO.Path]::GetRandomFileName() + $Extension)
          Write-Verbose "Creating file with random name in specified folder: '$__cttfFilePath'."
        } else { # presumptive path to a *file* specified
          if (-not [System.IO.Directory]::Exists((Split-Path $LiteralPath))) {
            Throw "Output folder '$(Split-Path $LiteralPath)' must exist."
          }
          $script:__cttfFilePath = $LiteralPath
          Write-Verbose "Using explicitly specified file path: '$__cttfFilePath'."
        }
      } else { # Create temp. file in the user's temporary folder.
        if (-not $prevFilePath) { 
          if ($Extension) {
            $script:__cttfFilePath = [IO.Path]::Combine([IO.Path]::GetTempPath(), [IO.Path]::GetRandomFileName() + $Extension)
          } else {
            $script:__cttfFilePath = [IO.Path]::GetTempFilename() 
          }
          Write-Verbose "Creating temp. file: $__cttfFilePath"
        } else {
          Write-Verbose "Reusing temp. file: $__cttfFilePath"      
        }
      }
      if (-not $BOM) { # UTF8 file *without* BOM
        # Note: Out-File, sadly, doesn't support creating UTF8-encoded files 
        #       *without a BOM*, so we must use the .NET framework.
        #       [IO.StreamWriter] by default writes UTF-8 files without a BOM.
        $sw = New-Object IO.StreamWriter $__cttfFilePath
        try {
            . $ScriptBlock | Out-String -Stream | % { $sw.WriteLine($_) }
        } finally { $sw.Close() }
      } else { # UTF8 file *with* BOM
        . $ScriptBlock | Out-File -Encoding utf8 $__cttfFilePath
      }
      return $__cttfFilePath
    }
  }
}

선택적으로 출력 [파일] 경로 및/또는 파일 이름 확장자를 지정하는 기능에 유의하세요.

답변2

큰따옴표로 묶지 않은 경우 $(...)PowerShell 개체(또는 포함된 코드에서 반환된 모든 것)를 반환하고 포함된 코드를 먼저 평가합니다. 이는 명령줄이 PowerShell이라고 가정할 때 사용자의 목적("[나]가 명령줄 중간에 끼어들 수 있는 항목")에 적합해야 합니다.

Get-Member다양한 버전을 에 파이핑하거나 직접 출력하여 이를 테스트할 수 있습니다 .

PS> "$(ls C:\Temp\Files)"
new1.txt new2.txt

PS> $(ls C:\Temp\Files)


    Directory: C:\Temp\Files


Mode                LastWriteTime         Length Name                                                                      
----                -------------         ------ ----                                                                      
-a----       02/06/2015     14:58              0 new1.txt                                                                  
-a----       02/06/2015     14:58              0 new2.txt   

PS> "$(ls C:\Temp\Files)" | gm


   TypeName: System.String
<# snip #>

PS> $(ls C:\Temp\Files) | gm


   TypeName: System.IO.FileInfo
<# snip #>

눈치채셨듯이 큰따옴표로 묶으면 `"$(...)"는 문자열만 반환합니다.

이런 방식으로 파일 내용을 한 줄에 직접 삽입하려면 다음과 같이 사용할 수 있습니다.

Invoke-Command -ComputerName (Get-Content C:\Temp\Files\new1.txt) -ScriptBlock {<# something #>}

관련 정보