TrueName.psm1

using namespace System.Collections.Generic
using namespace System.IO

function Get-TrueName {
    <#
    .SYNOPSIS
    Get the true name of a file or directory.
    .DESCRIPTION
    Gets the true name of the filename that you get by following symbolic links, network drive, virtual drives created using the SUBST command.
    .PARAMETER Path
    Specifies the path to one or more files or directorys for which you want to get the true names.
    Wildcard characters are permitted.
    .PARAMETER LiteralPath
    Specifies the path to one or more files or directorys for which you want to get the true names.
    The value of LiteralPath is used exactly as it's typed. No characters are interpreted as wildcards.
    .INPUTS
    System.Object
        You can pipe a string that contains a path to this function.
    .OUTPUTS
    System.String
    .EXAMPLE
    PS> Get-TrueName "C:\Users\All Users\Application Data\Microsoft"
    .EXAMPLE
    PS> net.exe use Z: \\localhost\C$\Windows
    PS> Get-TrueName Z:\System32
    #>

    [CmdletBinding(DefaultParameterSetName = 'Path')]
    [OutputType([string])]
    param (
        [Parameter(ParameterSetName = 'Path', Mandatory,
            ValueFromPipeline, ValueFromPipelineByPropertyName, Position = 0)]
        [string[]]$Path,
        [Parameter(ParameterSetName = 'LiteralPath', ValueFromPipelineByPropertyName, Mandatory)]
        [Alias('PSPath')]
        [string[]]$LiteralPath
    )

    begin {
        $ErrorActionPreference = 'Stop'
        $fileSystemProvider = Get-PSProvider FileSystem

        if ($PSVersionTable['PSVersion'].Major -le 5 -or $IsWindows) {
            $driveRoot = @{}
            Get-CimInstance Win32_MappedLogicalDisk | ForEach-Object { $driveRoot[$_.Name] = $_.ProviderName }

            subst.exe | ForEach-Object {
                $t = $_ -split '\\: => '
                $driveRoot[$t[0]] = $t[1]
            }
        }
    }

    process {
        try {
            $pathInFo = Resolve-Path @PSBoundParameters
        } catch {
            $PSCmdlet.WriteError($_)
            return
        }

        $pathInFo | ForEach-Object {
            try {
                $providerPath = $_.ProviderPath
                if ($_.Provider -ne $fileSystemProvider) {
                    return $providerPath
                }

                # Windows Virtual Drive
                if ($_.Drive) {
                    $drive = [Path]::GetPathRoot($providerPath) -replace '(/|\\)$'
                    if ($driveRoot.ContainsKey($drive)) {
                        return Get-TrueName -LiteralPath $providerPath.Replace($drive, $driveRoot[$drive])
                    }
                }

                # Soft Link
                $currrent = $providerPath
                $pathStack = [List[string]]::new()
                for (; ; ) {
                    $info = Get-Item -LiteralPath $currrent -Force
                    if (isSoftlink $info) {
                        $target = $info.ResolvedTarget
                        if (!$target) {
                            $target = $info.Target
                            if (!(Split-Path $target -IsAbsolute)) {
                                $target = "$((Resolve-Path -LiteralPath $currrent).ProviderPath)/../$target"
                            }
                        }
                        $pathStack.Reverse()
                        return Get-TrueName -LiteralPath $("$target/$($pathStack -join '/')" -replace '/$')
                    }
                    if (!$info.Directory -and !$info.Parent) { break }
                    $pathStack.Add($info.Name)
                    $currrent = Split-Path -LiteralPath $currrent
                }

                return $providerPath
            } catch {
                $PSCmdlet.WriteError($_)
            }
        }
    }
}

function isSoftlink {
    [OutputType([bool])]
    param ([FileSystemInfo]$info)

    switch ($info.LinkType) {
        SymbolicLink { return $true }
        AppExeCLink { return $true }
        Junction {
            $target = $info.Target
            if ($target -is [array]) { $target = $target[0] } # for PowerShell5.1
            $mountpointPattern = '^Volume\{[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}\}\\$'
            return $target -notmatch $mountpointPattern
        }
        Default { return $false }
    }
}

New-Alias Get-RealPath Get-TrueName