คำตอบนี้ไม่เหมาะสำหรับคุณหากคุณ:
- ไม่ค่อยบ่อยนักที่จะต้องใช้ CLI ภายนอก (ซึ่งโดยทั่วไปแล้วควรค่าแก่การพยายาม - คำสั่ง PowerShell-native เล่นได้ดีกว่ากันมากและไม่จำเป็นต้องใช้คุณสมบัติดังกล่าว)
- ไม่คุ้นเคยกับการทดแทนกระบวนการของ Bash
คำตอบนี้สำหรับคุณถ้าคุณ:
- ใช้ CLI ภายนอกบ่อยครั้ง (ไม่ว่าจะเป็นนิสัยหรือเนื่องมาจากการขาด (ดี) ทางเลือกของ PowerShell-native) โดยเฉพาะในขณะที่เขียนสคริปต์
- คุ้นเคยและชื่นชมสิ่งที่การสับเปลี่ยนกระบวนการของ Bash สามารถทำได้
- อัปเดต : ตอนนี้ PowerShell ได้รับการสนับสนุนบนแพลตฟอร์ม Unix ด้วยคุณสมบัตินี้เพิ่มความสนใจ - ดูคำขอคุณลักษณะนี้ใน GitHubซึ่งแสดงให้เห็นว่า PowerShell ใช้คุณสมบัติคล้ายกับการประมวลผลการทดแทน
ในโลกของ Unix ใน Bash / Ksh / Zsh การทดแทนโปรเซสเป็นการเสนอเอาท์พุทคำสั่งราวกับว่ามันเป็นไฟล์ชั่วคราวที่ทำความสะอาดหลังจากตัวมันเอง เช่นcat <(echo 'hello')
ที่cat
เห็นผลลัพธ์จากecho
คำสั่งเป็นเส้นทางของไฟล์ชั่วคราวที่มีออกคำสั่ง
ในขณะที่คำสั่ง PowerShell พื้นเมืองไม่จำเป็นจริงสำหรับคุณลักษณะดังกล่าวก็จะมีประโยชน์เมื่อต้องรับมือกับCLIs ภายนอก
การเลียนแบบคุณลักษณะใน PowerShell นั้นยุ่งยากแต่อาจคุ้มค่าถ้าคุณพบว่าตัวเองต้องการมันบ่อยๆ
รูปภาพฟังก์ชั่นที่ตั้งชื่อcf
ที่รับสคริปต์บล็อกเรียกใช้งานบล็อกและเขียนเอาต์พุตไปยัง temp ไฟล์ที่สร้างขึ้นตามความต้องการและส่งกลับ temp เส้นทางของแฟ้ม ; เช่น:
findstr.exe "Windows" (cf { Get-ChildItem c:\ }) # findstr sees the temp. file's path.
นี่เป็นตัวอย่างง่ายๆที่ไม่ได้แสดงให้เห็นถึงความต้องการคุณลักษณะดังกล่าวได้เป็นอย่างดี บางทีสถานการณ์สมมติที่น่าเชื่อถือมากขึ้นก็คือการใช้psftp.exe
SFTP ในการถ่ายโอน: การใช้แบตช์ (อัตโนมัติ) ต้องมีการเตรียมไฟล์อินพุตที่มีคำสั่งที่ต้องการในขณะที่คำสั่งดังกล่าวสามารถสร้างเป็นสตริงได้ทันที
เพื่อที่จะเข้ากันได้อย่างกว้างขวางกับโปรแกรมอรรถประโยชน์ภายนอกที่เป็นไปได้อุณหภูมิ ไฟล์ควรใช้UTF 8เข้ารหัสโดยไม่ต้อง BOM (เครื่องหมายไบต์ตามลำดับ) โดยค่าเริ่มต้นถึงแม้ว่าคุณจะสามารถขอ UTF-8 BOM ด้วย-BOM
ถ้าจำเป็น
แต่น่าเสียดายที่โดยอัตโนมัติทำความสะอาดทุกแง่มุมของการแทนกระบวนการไม่สามารถโดยตรงเทิดทูนดังนั้นการเรียกร้องการทำความสะอาดอย่างชัดเจนเป็นสิ่งจำเป็น ; การล้างข้อมูลจะดำเนินการโดยการโทรcf
โดยไม่มีข้อโต้แย้ง :
สำหรับการใช้แบบอินเตอร์แอคทีฟคุณสามารถทำให้การล้างข้อมูลเป็นไปโดยอัตโนมัติโดยการเพิ่มการเรียก cleanup ไปยังprompt
ฟังก์ชันของคุณดังต่อไปนี้ ( prompt
ฟังก์ชั่นส่งกลับสตริงพรอมต์แต่ยังสามารถใช้เพื่อดำเนินการคำสั่งเบื้องหลัง$PROMPT_COMMAND
ตัวแปร); สำหรับความพร้อมใช้งานในเซสชันแบบโต้ตอบใด ๆ ให้เพิ่มข้อมูลต่อไปนี้รวมทั้งคำจำกัดความcf
ด้านล่างไว้ในโปรไฟล์ PowerShell ของคุณ:
"function prompt { cf 4>`$null; $((get-item function:prompt).definition) }" |
Invoke-Expression
สำหรับใช้ในสคริปต์เพื่อให้แน่ใจว่ามีการดำเนินการล้างข้อมูลบล็อกที่ใช้cf
- อาจเป็นสคริปต์ทั้งหมด - ต้องถูกล้อมรอบด้วย a try
/ finally
block ซึ่งcf
ไม่มีข้อโต้แย้งที่เรียกว่าการล้างข้อมูล:
# 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
:
หมายเหตุ : การใช้งานNew-Module
ซึ่งต้องการ PSv3 + เพื่อกำหนดฟังก์ชั่นผ่านโมดูลแบบไดนามิกช่วยให้มั่นใจได้ว่าจะไม่มีความขัดแย้งของตัวแปรระหว่างพารามิเตอร์ฟังก์ชันและตัวแปรที่อ้างอิงภายในบล็อกสคริปต์ที่ส่งผ่าน
$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
}
}
}
หมายเหตุความสามารถในการระบุทางเลือกเส้นทาง [ไฟล์] และ / หรือชื่อไฟล์นามสกุล