问题
I'd like to be able to type quick, simple commands that manipulate files in-place. For example:
# prettify an XML file
format-xml foo | out-file foo
This won't work because the pipeline is designed to be "greedy." The downstream cmdlet acquires a Write lock to the file as soon as the upstream cmdlet processes the first line of input, which stalls the upstream cmdlet from reading the rest of the file.
There are many possible workarounds: write to temporary files, separate operations into multiple pipelines (storing intermediate results in variables), or similar. But I figure this is a really common task for which someone has developed a quick, shell-friendly shortcut.
I tried this:
function Buffer-Object
{
[CmdletBinding()]
param (
[parameter(Mandatory=$True, ValueFromPipeline=$True)]
[psobject] $InputObject
)
begin { $buf = new-list psobject }
process { $buf.Add($InputObject) }
end { $buf }
}
format-xml foo | buffer-object | out-file foo
It works ok in some situations. Mapped to a short alias and rolled into a common distribution like PSCX, it would be "good enough" for quick interactive tasks. Unfortunately it appears that some cmdlets (including out-file) grab the lock in their Begin{} method rather than in Process{}, so it does not solve this particular example.
Other ideas?
回答1:
As far as I remember (can't test now), you can read a whole file into memory with the namespace notation:
${c:file1.txt} = ${c:file1.txt} -replace "a" "o"
来源:https://stackoverflow.com/questions/1035026/powershell-how-do-you-read-write-i-o-within-one-pipeline