Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

On Windows, a directory symlink doesn't behave a like a directory with Get-ChildItem if its target path is a relative path that starts directly with a name #15161

Closed
mklement0 opened this issue Apr 5, 2021 · 2 comments
Labels
Needs-Triage The issue is new and needs to be triaged by a work group. WG-Cmdlets-Core cmdlets in the Microsoft.PowerShell.Core module WG-Engine-Providers built-in PowerShell providers such as FileSystem, Certificates, Registry, etc.

Comments

@mklement0
Copy link
Contributor

mklement0 commented Apr 5, 2021

Note: This is ultimately a duplicate of #15235


PR #8783 brought the ability to use relative paths as symlink targets on Windows.

However, if the target is a directory and the relative path starts with / is just a name (rather than starting with .\), the resulting symlink doesn't behave like a directory with Get-ChildItem.

Note that on Unix, as of PowerShell Core 7.2.0-preview.4, use of relative target paths is still fundamentally unsupported - see #15233

Steps to reproduce

Run on Windows:

# Switch to a temporary directory.
Push-Location -ea Stop ($tmpDir = (New-Item -Type Directory -Force (Join-Path Temp:/ $PID)).FullName)

# Create a dir. to serve as the target, with a single text file in it.
$null = New-Item -Type Directory target -Force
'hi' > target/t.txt

# Define two links: 
#  * one that targets 'target' - by name only.
#  * one that targets '.\target' - explicit reference to the current dir.
$null = New-Item -Type SymbolicLink link1 -Target target -Force
$null = New-Item -Type SymbolicLink link2 -Target .\target -Force

# Now compare the Get-ChildItem behavior of these two links, which
# *should* be the same.
Get-ChildItem link1
Get-ChildItem link2

Pop-Location; Remove-Item -lp $tmpDir -Recurse

Expected behavior

With the exception of the directory path in the grouping header, the commands should produce the same output and show the content of the target dir:

    Directory: C:\Users\jdoe\AppData\Local\Temp\8748\link1

Mode                 LastWriteTime         Length Name
----                 -------------         ------ ----
-a---            4/5/2021  3:30 PM              4 t.txt

    Directory: C:\Users\jdoe\AppData\Local\Temp\8748\link2

Mode                 LastWriteTime         Length Name
----                 -------------         ------ ----
-a---            4/5/2021  3:30 PM              4 t.txt

Actual behavior

    Directory: C:\Users\jdoe\AppData\Local\Temp\8748

Mode                 LastWriteTime         Length Name
----                 -------------         ------ ----
la---            4/5/2021  3:30 PM              0 link1 -> target

    Directory: C:\Users\jdoe\AppData\Local\Temp\8748\link2

Mode                 LastWriteTime         Length Name
----                 -------------         ------ ----
-a---            4/5/2021  3:30 PM              4 t.txt

Note how link1 present as if it were a flle, as if you had called Get-Item rather than Get-ChildItem on it.

Interestingly, cmd.exe's dir shows analogous behavior, and additionally fails with dir link1\t.txt, which PowerShell handles correctly.

Environment data

PowerShell Core v7.2.0-preview.4 (.NET 6.0.0-preview.2.21154.6) on Microsoft Windows 10 Pro (64-bit; Version 20H2, OS Build: 19042.867)
@mklement0 mklement0 added the Needs-Triage The issue is new and needs to be triaged by a work group. label Apr 5, 2021
@iSazonov iSazonov added WG-Cmdlets-Core cmdlets in the Microsoft.PowerShell.Core module WG-Engine-Providers built-in PowerShell providers such as FileSystem, Certificates, Registry, etc. labels Apr 14, 2021
@237dmitry
Copy link

I did not understand what the problem is.

11

@mklement0
Copy link
Contributor Author

mklement0 commented Apr 15, 2021

@237dmitry, if you run the code in the initial post, you'll see the problem.

It doesn't always happen, but I've just realized that this issue will go away if what @MatejKafka reported in #15235 gets fixed (which is the right thing to do), so I'm closing this.

In short: if there's a mismatch between the process' current directory (as reported by [Environment]::CurrentDir) and PowerShell's (which is typically the case), the symlink target's type (file vs. directory) may be mis-identified.

In the case at hand, target - but not .\target - is mistakenly looked for in [Environment]::CurrentDir and, if there's no such item there, it is assumed to be a file, so that the link1 symlink is created with the wrong type (it behaves like a file, even though its true target is a directory).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Needs-Triage The issue is new and needs to be triaged by a work group. WG-Cmdlets-Core cmdlets in the Microsoft.PowerShell.Core module WG-Engine-Providers built-in PowerShell providers such as FileSystem, Certificates, Registry, etc.
Projects
None yet
Development

No branches or pull requests

3 participants