-
Notifications
You must be signed in to change notification settings - Fork 8.1k
Description
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.pdfOn 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
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 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)