PowerShell copy fails without warning
Anytime you're having problems trying to figure out why a parameter doesn't bind correctly in PowerShell, use Trace-Command like so:
Trace-Command -Name ParameterBinding -expr { copy-item $f foo.cat.bak } -PSHost
In this case, it works for me. Perhaps this is a "feature" of PowerShell 2.0 but you can see it attempt to bind several different times before it hits on:
COERCE arg to [System.String] Trying to convert argument value from System.Management.Automation.PSObject to System.String CONVERT arg type to param type using LanguagePrimitives.ConvertTo CONVERT SUCCESSFUL using LanguagePrimitives.ConvertTo: [C:\Users\Keith\foo.cat]
The way this normally works when the FileInfo objects are passed via the pipeline, they bind by "PropertyName" to the LiteralPath parameter. I know, you're probably wondering, uh didn't think System.IO.FileInfo had a LiteralPath property. Heheh, it doesn't. Those tricky PowerShell folks snuck a PSPath alias onto the LiteralPath parameter and PowerShell "adapts" each the FileInfo object to add a number of PS* properties including PSPath. So if you wanted to "literally" match the pipelining behavior you would use:
Copy-Item -LiteralPath $f.PSPath $targetDir -force
Note that you don't have to quote $targetDir in this case (as a parameter argument).
The reason why copy-item
doesn't work is that you pass System.IO.FileInfo
as parameter -path
.There are two possibilities how to do it correctly:
copy-item -literal $f.Fullname -destination ...
$f | copy-item -destination ...
Note that I use parameter -literalPath
because files in the temp folder have usually [
and ]
inside the name which acts as wildcards characters.
If you wonder why case #2 works, have a look at 'help Copy-Item -Parameter Path`, you will see Accept pipeline input? true (ByValue, ByPropertyName). For more info what it means look at Keith's ebook Effective Windows PowerShell.
Why you version doesn't work? Because paramerer -path
(which is at position 1) takes input of type [string[]]
and not FileInfo
. So PowerShell tried to convert it to [string]
(and then to the array) but it probably used only Name
property. You can try it like this:
[string[]] (gci | select -first 1)