6

In powershell, you use cd dir to go into the directory dir.

But if dir is a shortcut to a directory, cd dir and cd dir.lnk both give an error, saying that the directory doesn't exist.

So how do I follow that shortcut?

(In Linux cd dir just works. In Windows, I've got no idea)

falsePockets
  • 3,826
  • 4
  • 18
  • 37
  • 1
    Windows shortcut is actually [a binary file](https://msdn.microsoft.com/en-us/library/dd871305.aspx) that needs explicit parsing or [COM access](https://stackoverflow.com/q/9414152). NTFS supports symbolic links too (like the Ext fs in Linux), but those are seldom used. – vonPryz Sep 18 '17 at 10:10
  • See also: https://stackoverflow.com/questions/54728510/how-to-follow-a-symbolic-soft-link-in-cmd-or-powershell – DefinedRisk Dec 08 '20 at 09:59

3 Answers3

5

Using the shell com-object, you can get the target path and from there, do what you wish. Get-ShortcutTargetPath

function Get-ShortcutTargetPath($fileName) {
    $sh = New-Object -COM WScript.Shell
    $targetPath = $sh.CreateShortcut($fileName).TargetPath 
    [System.Runtime.Interopservices.Marshal]::ReleaseComObject($sh) | Out-Null
    return $targetPath
}


$file = 'Path\to\Filename.lnk'
$TargetPath = Get-shortcutTargetPath($file)

if (Test-Path -PathType Leaf $TargetPath) {
    $TargetPath = Split-Path -Path $TargetPath
}

Set-Location $TargetPath
Sage Pourpre
  • 9,932
  • 3
  • 27
  • 39
  • 1
    The `$TargetPath` contains the executable name which cannot be used with `Set-Location`. Perhaps `Set-Location $(Split-Path -Path $TargetPath)` – lit Feb 18 '19 at 13:37
  • @lit Indeed. I edited my code to include a `Split-Path` based on your comment. If the target is a container though, it is important to not perform the Split-Path, otherwise you'll get the parent container of the target container. – Sage Pourpre Feb 18 '19 at 23:53
0

The other answers don't actually work for me, the first does nothing and the second gives me the error "The shortcut pathname must end with .lnk or .url."

However, after digging through MSDN for a while I worked out a solution. I have no idea why I can't find any answers to this on Google, but I even travelled to the untouched second and third pages and tried multiple keywords... I guess the search results are just buried for some reason. But here's how I solved the problem. Using a while loop and the Get-Item command, you can follow a symbolic link to it's true path! Works for directory links, too.

So far the double-cd approach is the most reliable/universal I can find for handling a situation of mixed relative/absolute paths in the filenames and targets, and I tested several scenarios.

function getLinkTarget($fn) {
    $op=$PWD #Save original path
    while($t=(Get-Item $fn).Target) { #Get link target
        cd (Split-Path -Parent $fn) #cd to parent of file/dir
        cd (Split-Path -Parent $t) #cd again to parent of target
        $fn=(Split-Path -Leaf $t) #Set filename to relative target
    }
    $fn=(Join-Path $PWD $fn) #Make path absolute
    cd $op #Change back to original path
    return $fn
}
Eric Aya
  • 69,473
  • 35
  • 181
  • 253
Pecacheu
  • 368
  • 1
  • 3
  • 13
-1

In Windows 10 cd directory_name or cd dir* if you only want part of the name assuming no other directories start with the same dir*.

enter image description here

dxander
  • 99
  • 1
  • 5