PS C:\Users\robert.lee> new-item C:\temp\junk\delete-me
PS C:\Users\robert.lee> $d=get-childitem C:\temp\junk -file
PS C:\Users\robert.lee> remove-item $d
/* This does NOT delete C:\temp\junk\delete-me, but deletes C:\Users\robert.lee\delete-me. */
PS C:\Users\robert.lee> $d | remove-item
/* This does delete C:\temp\junk\delete-me. */
Why remove-item $d
does not know where to find the file (C:\temp\junk
) while $d | remove-item
does? The object $d has the full path in either case.
PS: remove-item $d
does remove file in another location, as tested on PSVersion 7.2.1 on macOS Monterey:
PS /Users/robert.lee/m/Windows> $d=get-childitem /tmp/Junk2 -file
PS /Users/robert.lee/m/Windows> ls /tmp/Junk2
delete-me
PS /Users/robert.lee/m/Windows> remove-item $d
PS /Users/robert.lee/m/Windows> ls /tmp/Junk2
PS /Users/robert.lee/m/Windows>
CodePudding user response:
PowerShell can only do so much for you, and one thing it can't do, is guess what you're after all the time. The issue you're having comes from the parameter binding going on behind the scenes. So, the binding with Remove-Item $g
only happens to the Name
property from the [FileInfo]
object passed to it, which will coerce the object into a string and then tie it to the current working directory binding it to Path.
Whereas, $g | Remove-Item
, the binding from the pipeline is bound using a different procedure and takes the PSPath instance member and binds it to the LiteralPath which is the FullName property in your [FileInfo]
object.
- Still coerces the object into an object of
[string]
, just using a different property. - Sauce for an okay understanding of ParameterBinding.
- Using
Trace-Command
, you can get a much better understanding of this.
- Using
Long story short, use $g.FullName
for both scenarios as it will output an object of [string]
, and both Path parameters accept the entirety of the value, by pipeline as well.