Skip to content

Stringification behavior of FileInfo / Directory instances has changed since v6.0.2 #7132

Closed

Description

How FileInfo / DirectoryInfo instances stringify implicitly used to depend on the specifics of the Get-ChildItem call that emitted them.

Previously, a Get-ChildItem command that targeted a directory path only would yield child items that stringified to their mere name rather than to their full path.

This now behaves differently in PowerShell Core v6.1.0-preview.3.

While the new behavior is more predictable and would actually resolve part of #6057, it is a - presumably unintended - breaking change.

Steps to reproduce

Create a temp. dir tmpDir with single file tmpFile, then use Get-ChildItem to enumerate tmpDir and stringify the resulting item:

$null > (Join-Path (New-Item -force -Type Directory tmpDir) tmpFile); Get-ChildItem tmpdir | % { "$_" }

Expected behavior

tmpFile

That is, only the file's name is reported.
This is what happened up until at least v6.0.2, and still happens in Windows PowerShell.

Actual behavior

/Users/jdoe/tmpdir/tmpFile

That is, stringification now results in the full path.

Environment data

PowerShell Core v6.1.0-preview.3

Activity

  1. changed the title [-]in:title get-childitem[/-] [+]Stringification behavior of FileInfo instances has changed since v6.0.2[/+] on Jun 21, 2018
  2. changed the title [-]Stringification behavior of FileInfo instances has changed since v6.0.2[/-] [+]Stringification behavior of FileInfo / Directory instances has changed since v6.0.2[/+] on Jun 21, 2018
  3. iSazonov commented on Jun 21, 2018

    @iSazonov
    Collaborator

    I think it come from .Net Core 2.0 -> 2.1 update.

    $a=[io.fileinfo]::new("C:\Windows\explorer.exe")
    $a.ToString()
    cd "C:\Windows"
    $b=[io.fileinfo]::new(".\explorer.exe")
    $b.ToString()
  4. mklement0 commented on Jun 21, 2018

    @mklement0
    ContributorAuthor

    Ilya (@iSazonov):

    Probably not, given that the behavior in your examples is no different from the one in Windows PowerShell v2 - v5.1 .

    Something must have changed in the way PowerShell constructs such instances.

  5. iSazonov commented on Jun 22, 2018

    @iSazonov
    Collaborator

    I can confirm that now we call obj.ToString() for FileInfo objects but I can't find what's changed in code.

  6. added
    WG-Enginecore PowerShell engine, interpreter, and runtime
    Issue-Discussionthe issue may not have a clear classification yet. The issue may generate an RFC or may be reclassif
    on Jun 22, 2018
  7. SeeminglyScience commented on Jun 26, 2018

    @SeeminglyScience
    Contributor

    Just ran into this as well.

    Here's the commit in corefx where the ToString behavior was changed.

    Here's that line specifically. Edit: nvm, not at all relevant :)

  8. mklement0 commented on Jun 26, 2018

    @mklement0
    ContributorAuthor

    Patrick Meinecke (@SeeminglyScience):

    Thanks, but I don't think that explains it. The only .ToString()-relevant change in that commit is to remove the transformation of a path like c: (i.e., a drive-letter-only path) to . via the now-removed ShouldReviseDirectoryPathToCurrent() method, something that the commit message calls a "limited trust holdover".

    The fundamental behavior hasn't changed: whatever path you pass in to construct the instance is output by .ToString().

    Thus, something on the PowerShell side must have changed:

    Ilya (@iSazonov), when you say "now we call obj.ToString()", can you point us to the relevant code?

  9. iSazonov commented on Jun 26, 2018

    @iSazonov
    Collaborator
  10. rjmholt commented on Jun 6, 2019

    @rjmholt
    Collaborator

    Copying some things from the duplicate issue I just closed...

    Looks like .NET is leaning toward WontFix.

    We should:

    • Investigate changing LanguagePrimitives so that converting a DirectoryInfo to a string uses Name rather than ToString()
    • Investigate investment in Keith Hill (@rkeithhill)'s suggested [Path()] attribute (or a similar parameter processing attribute)
    • Update any relevant documentation

    More info in https://github.com/dotnet/corefx/issues/38215.

    /cc Steve Lee (@SteveL-MSFT) and Joey Aiello (@joeyaiello) since we should amend changelogs.

    Also tagging for @PowerShell/powershell-committee review

  11. rjmholt commented on Jun 6, 2019

    @rjmholt
    Collaborator

    Thus, something on the PowerShell side must have changed:

    .NET team verified a change of theirs broke this. I have a repro in the issue I opened in CoreFX

  12. 17 remaining items

  13. iSazonov commented on Jun 13, 2019

    @iSazonov
    Collaborator

    backwards compatibility is a major concern

    If .Net Core found this accessible we could do the same.

    Perhaps PSSA could help. /cc Rob Holt (@rjmholt) Christoph Bergmeister (@bergmeister)

    Not clear about ETS. I'd expect that we fix only dir output in formatting system.

  14. rjmholt commented on Jun 13, 2019

    @rjmholt
    Collaborator

    explore an ETS solution

    ETS meaning extended type system? So some kind of script method override? (This is what I was imagining too).

    PSScriptAnalyzer doesn't currently have any single rule tracking semantic changes in PowerShell. I think that kind of effort could only really proceed with help from PowerShell. I think we've discussed exactly this before, the idea where we have a big rule that just looks up the PowerShell version and checks the particular syntax.

    If we can at least catalogue the nature of any and all breaking changes in one place, such a rule would be feasible to write.

    Also, I feel I should register that despite making the opposing case, I'm actually in favour of the new behaviour.

  15. iSazonov commented on Jun 13, 2019

    @iSazonov
    Collaborator

    ETS meaning extended type system?

    Yes.

    I think we've discussed exactly this before

    Have we a tracking issue?

  16. daxian-dbw commented on Jun 13, 2019

    @daxian-dbw
    Member

    Recommendation is to explore an ETS solution and measure the level of compatibility as well as the perf impact before agreeing that would be the final solution.

    ETS won't be helpful to retain the old behavior in PowerShell. As described in #7132 (comment), the root cause of the original inconsistent behavior in PowerShell is the inconsistency in returning result of FileInfo.ToString(). When invoking Get-ChildItem against a directory, it uses DirectoryInfo.EnumerateFiles() to get the FileInfo objects, which return the file name only when calling ToString() on them. When invoking Get-ChildItem against files directly, it uses the public constructor new FileInfo(string fileName) to create the FileInfo objects, which return the full path when calling ToString() on them.

    So to retain the old wrong behavior, we will have to put some hacky code in FileSystemProvider to differentiate the FileInfo objects generated from Get-ChildItem <dir> and Get-ChildItem <file> and Get-Item <file>. That code would be definitely confusing and I don't think we should do that just in order to retain an unfavorable existing behavior. Since .NET accepted the breaking change by fixing the inconsistency, it's a good chance for us to do the same.

  17. vexx32 commented on Jun 13, 2019

    @vexx32
    Collaborator

    I don't think it makes sense to retain the more confusing behaviour just because people are accustomed to dealing with it.

    Keeping this change means some scripts will break, maybe, but in fixing those we'd just be removing additional workaround logic that was probably more annoying to have around anyway.

    Maybe a small handful of edge cases where it really was helpful, but there is no shortage of available alternatives for those, either. 🙂

  18. rjmholt commented on Jun 13, 2019

    @rjmholt
    Collaborator

    Have we a tracking issue?

    #9138

  19. added
    Review - CommitteeThe PR/Issue needs a review from the PowerShell Committee
    Committee-ReviewedPS-Committee has reviewed this and made a decision
    and removed
    Committee-ReviewedPS-Committee has reviewed this and made a decision
    Review - CommitteeThe PR/Issue needs a review from the PowerShell Committee
    on Jun 13, 2019
  20. SteveL-MSFT commented on Jun 19, 2019

    @SteveL-MSFT
    Member

    @PowerShell/powershell-committee reviewed this. The work involved to maintain compatibility is not worth the effort as the underlying platform has introduced a change to fix an inconsistency problem. This results in a breaking change for some PowerShell users, but detecting of this will be quick and using .FullName or .Name as appropriate is the right thing to do. We could make a change in Join-Path to support joining two absolute paths to make this simpler for scripts, but that would be a separate issue.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    Breaking-Changebreaking change that may affect usersCommittee-ReviewedPS-Committee has reviewed this and made a decisionIssue-Discussionthe issue may not have a clear classification yet. The issue may generate an RFC or may be reclassifResolution-ExternalThe issue is caused by external component(s).WG-Enginecore PowerShell engine, interpreter, and runtime

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions