Câu trả lời này KHÔNG dành cho bạn , nếu bạn:
- hiếm khi, nếu cần, sử dụng CLI bên ngoài (thường đáng để phấn đấu - Các lệnh gốc PowerShell chơi tốt hơn nhiều và không cần tính năng như vậy).
- không quen thuộc với quá trình thay thế của Bash.
Câu trả lời này là dành cho bạn , nếu bạn:
- thường xuyên sử dụng CLI bên ngoài (cho dù không theo thói quen hoặc do thiếu các lựa chọn thay thế gốc PowerShell), đặc biệt là trong khi viết tập lệnh.
- được sử dụng và đánh giá cao những gì thay thế quá trình của Bash có thể làm.
- Cập nhật : Hiện tại PowerShell cũng được hỗ trợ trên các nền tảng Unix, tính năng này ngày càng được quan tâm - xem yêu cầu tính năng này trên GitHub, điều này cho thấy PowerShell triển khai một tính năng gần giống với quá trình thay thế.
Trong thế giới Unix, trong Bash / Ksh / Zsh, một sự thay thế quá trình đang cung cấp xử lý đầu ra lệnh như thể nó là một tệp tạm thời tự dọn sạch; ví dụ cat <(echo 'hello'), trong đó catxem đầu ra từ echolệnh là đường dẫn của tệp tạm thời chứa đầu ra lệnh .
Mặc dù các lệnh gốc PowerShell không có nhu cầu thực sự cho tính năng như vậy, nhưng nó có thể hữu ích khi xử lý các CLI bên ngoài .
Mô phỏng tính năng trong PowerShell rất cồng kềnh , nhưng có thể đáng giá, nếu bạn thấy mình cần nó thường xuyên.
Hình ảnh một chức năng có tên cfchấp nhận một khối tập lệnh, thực thi khối và ghi đầu ra của nó vào một temp. tập tin được tạo theo yêu cầu và trả về temp. đường dẫn của tập tin ; ví dụ:
findstr.exe "Windows" (cf { Get-ChildItem c:\ }) # findstr sees the temp. file's path.
Đây là một ví dụ đơn giản không minh họa sự cần thiết của một tính năng như vậy. Có lẽ một kịch bản thuyết phục hơn là việc sử dụng psftp.exeđể chuyển SFTP: việc sử dụng lô (tự động) của nó yêu cầu cung cấp một tệp đầu vào có chứa các lệnh mong muốn, trong khi các lệnh như vậy có thể dễ dàng được tạo thành một chuỗi khi đang di chuyển.
Vì vậy, để tương thích rộng rãi với các tiện ích bên ngoài càng tốt, temp. tập tin nên sử dụng UTF-8 mã hóa mà không có một BOM (byte-trật tự dấu) theo mặc định, mặc dù bạn có thể yêu cầu một BOM UTF-8 với -BOM, nếu cần thiết.
Thật không may, khía cạnh dọn dẹp tự động của các thay thế quá trình không thể được mô phỏng trực tiếp , vì vậy cần có một cuộc gọi dọn dẹp rõ ràng ; dọn dẹp được thực hiện bằng cách gọi cf mà không có đối số :
Để sử dụng tương tác , bạn có thể tự động hóa việc dọn dẹp bằng cách thêm lệnh gọi dọn dẹp vào promptchức năng của mình như sau ( prompthàm trả về chuỗi dấu nhắc , nhưng cũng có thể được sử dụng để thực hiện các lệnh phía sau hậu trường mỗi khi dấu nhắc được hiển thị, tương tự như của Bash $PROMPT_COMMANDBiến đổi); để có sẵn trong bất kỳ phiên tương tác nào, hãy thêm thông tin sau đây cũng như định nghĩa cfbên dưới vào hồ sơ PowerShell của bạn:
"function prompt { cf 4>`$null; $((get-item function:prompt).definition) }" |
Invoke-Expression
Để sử dụng trong các tập lệnh , để đảm bảo việc dọn dẹp được thực hiện, khối sử dụng cf- có khả năng là toàn bộ tập lệnh - cần phải được gói trong một khối try/ finallytrong đó cfkhông có đối số được gọi để dọn dẹp:
# 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.
}
Đây là cách triển khai : chức năng nâng cao ConvertTo-TempFilevà bí danh cô đọng của nó , cf:
Lưu ý : Việc sử dụng New-Module, yêu cầu PSv3 +, để xác định hàm thông qua mô-đun động đảm bảo rằng không thể có xung đột biến giữa các tham số chức năng và các biến được tham chiếu bên trong khối tập lệnh được truyền.
$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
}
}
}
Lưu ý khả năng tùy chọn chỉ định đường dẫn [tệp] đầu ra và / hoặc phần mở rộng tên tệp.