Summary of the new feature/enhancement
Provide the ability to resolve a filesystem path to its canonical path, such as by adding a -Canonical switch to the Convert-Path cmdlet.
In short: The idea is to allow you to answer the following question:
Given a (possibly relative, possibly PS-drive-based) file or directory path, where does the referenced file truly live, with symlinks, if any, resolved to their underlying target location, expressed as an absolute, native filesystem path?
For instance, say you want to know the canonical path of file
/User Guides And Information/ENERGY STAR.pdf on a Mac, which is /Library/Documentation/User Guides and Information.localized/ENERGY STAR.pdf
because /User Guides And Information is a directory symlink that targets
directory /Library/Documentation/User Guides and Information.localized
You could then do something like:
# WISHFUL THINKING
PS> Convert-Path -Canonical '/User Guides And Information/ENERGY STAR.pdf'
/Library/Documentation/User Guides and Information.localized/ENERGY STAR.pdf
On at least some Linux distros, the realpath utility provides this functionality, and you can also use readlink -f (or -m or -e).
Note that this new feature would complement the existing ability to inspect a symlink's (reparse point's) target via the .Target property of Get-Item / Get-ChildItem output, and also the proposed .ResolvedTarget property (see #13366 ).
The latter only operate on symlinks themselves, not on paths based on them (paths with additional components); additionally, the .Target property may be a relative path and $null if the input path isn't a symlink.
That is, (Get-Item '/User Guides And Information').Target works, because /User Guides And Information is itself a symlink, but (Get-Item '/User Guides And Information/ENERGY STAR.pdf').Target is $null, because the file inside the directory-symlink path itself isn't a symlink and therefore has no .Target property value.
Proposed technical implementation details (optional)
-
Windows: The GetFinalPathNameByHandle Windows API function provides this functionality.
-
macOS, Linux: haven't looked into it, but the GNU readlink utility implementation should provide pointers. The POSIX-mandated realpath() function provides this functionality (implemented as library functions on macOS and Linux; see man 3 realpath).
Decisions will also have to be made with respect to how final path components that don't exist yet are handled (i.e., a prefix of the path exists (an ancestral directory), but not the filename part or a relative subdirectory-based path), and how to handle broken symlinks; these cases are reflected in the GNU readlink utility's related -f / -e / -m options.
Note that Convert-Path in its current form doesn't support (partially) non-existent paths, but it's about time we changed that too - see #2993
Update: Implementing this functionality as a .NET API that this feature could build on, in the form of a new System.IO.Path.GetFullPath() overload, has now been proposed: dotnet/runtime#24271 (comment)
Summary of the new feature/enhancement
Provide the ability to resolve a filesystem path to its canonical path, such as by adding a
-Canonicalswitch to theConvert-Pathcmdlet.In short: The idea is to allow you to answer the following question:
Given a (possibly relative, possibly PS-drive-based) file or directory path, where does the referenced file truly live, with symlinks, if any, resolved to their underlying target location, expressed as an absolute, native filesystem path?
For instance, say you want to know the canonical path of file
/User Guides And Information/ENERGY STAR.pdfon a Mac, which is/Library/Documentation/User Guides and Information.localized/ENERGY STAR.pdfbecause
/User Guides And Informationis a directory symlink that targetsdirectory
/Library/Documentation/User Guides and Information.localizedYou could then do something like:
On at least some Linux distros, the
realpathutility provides this functionality, and you can also usereadlink -f(or-mor-e).Note that this new feature would complement the existing ability to inspect a symlink's (reparse point's) target via the
.Targetproperty ofGet-Item/Get-ChildItemoutput, and also the proposed.ResolvedTargetproperty (see #13366 ).The latter only operate on symlinks themselves, not on paths based on them (paths with additional components); additionally, the
.Targetproperty may be a relative path and$nullif the input path isn't a symlink.That is,
(Get-Item '/User Guides And Information').Targetworks, because/User Guides And Informationis itself a symlink, but(Get-Item '/User Guides And Information/ENERGY STAR.pdf').Targetis$null, because the file inside the directory-symlink path itself isn't a symlink and therefore has no.Targetproperty value.Proposed technical implementation details (optional)
Windows: The
GetFinalPathNameByHandleWindows API function provides this functionality.macOS, Linux:
haven't looked into it, but the GNU. The POSIX-mandatedreadlinkutility implementation should provide pointersrealpath()function provides this functionality (implemented as library functions on macOS and Linux; seeman 3 realpath).Decisions will also have to be made with respect to how final path components that don't exist yet are handled (i.e., a prefix of the path exists (an ancestral directory), but not the filename part or a relative subdirectory-based path), and how to handle broken symlinks; these cases are reflected in the GNU
readlinkutility's related-f/-e/-moptions.Note that
Convert-Pathin its current form doesn't support (partially) non-existent paths, but it's about time we changed that too - see #2993Update: Implementing this functionality as a .NET API that this feature could build on, in the form of a new
System.IO.Path.GetFullPath()overload, has now been proposed: dotnet/runtime#24271 (comment)