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 đó cat
xem đầu ra từ echo
lệ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 cf
chấ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 prompt
chức năng của mình như sau ( prompt
hà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_COMMAND
Biế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 cf
bê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
/ finally
trong đó cf
khô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-TempFile
và 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.