Solved Any way to reference the current drive, even if its letter changes?

pluviosilla

New member
Local time
5:07 PM
Messages
8
I would like to create symbolic links and / or shortcuts on a portable drive that remain valid even when the drive letter changes. The links are to folders on the same drive.

I assume there is no environmental variable like %SystemDrive% that references the current drive. Is there any way to use junction points or soft links to accomplish this?
 

My Computer My Computer

At a glance

TXIntell(R) Core(TM) i5-2400 CPU 3.10 GHz 3.30 GHz16GBNone
Computer type
PC/Desktop
Computer Manufacturer/Model Number
Custom Build
OS
TX
CPU
Intell(R) Core(TM) i5-2400 CPU 3.10 GHz 3.30 GHz
Motherboard
Gigabyte GA-Z68MA-D2H-B3
Memory
16GB
Graphics Card(s)
None
Hard Drives
Two SSD drives, Two SATA hard disks
Um... In Windows symbolic links support relative paths and a path that begins with `\` references the root folder of the current drive. So, in your case just create a symbolic link that references your desired path, just start that path with `\` (no drive letter). Done.

I just tried this by creating a root folder `Test` and then creating a symbolic link to `\Test` elsewhere on the same drive. If works fine regardless of the current drive letter.

Directory junctions do not work that way - they require absolute path beginning with the drive letter. But symbolic links accept relative paths and work perfectly fine in that role.
 

My Computer My Computer

At a glance

Windows 7 Pro x64
Computer type
PC/Desktop
OS
Windows 7 Pro x64
Interesting suggestion. Certainly worth a try, but I find that I can create the symbolic link without referencing the drive letter, but Windows simply inserts the letter in the Target path. In other words, the "\" is a nice shorthand when running the mklink command but does not get rid of the absolute path, including the drive letter, that is assigned to the link.
 

My Computer My Computer

At a glance

TXIntell(R) Core(TM) i5-2400 CPU 3.10 GHz 3.30 GHz16GBNone
Computer type
PC/Desktop
Computer Manufacturer/Model Number
Custom Build
OS
TX
CPU
Intell(R) Core(TM) i5-2400 CPU 3.10 GHz 3.30 GHz
Motherboard
Gigabyte GA-Z68MA-D2H-B3
Memory
16GB
Graphics Card(s)
None
Hard Drives
Two SSD drives, Two SATA hard disks
BTW, I just discovered that I can edit desktop.ini files to reference folder icons using relative paths. I am hoping I can find a way to create shortcuts or symbolic links using relative paths in a similar manner.
 

My Computer My Computer

At a glance

TXIntell(R) Core(TM) i5-2400 CPU 3.10 GHz 3.30 GHz16GBNone
Computer type
PC/Desktop
Computer Manufacturer/Model Number
Custom Build
OS
TX
CPU
Intell(R) Core(TM) i5-2400 CPU 3.10 GHz 3.30 GHz
Motherboard
Gigabyte GA-Z68MA-D2H-B3
Memory
16GB
Graphics Card(s)
None
Hard Drives
Two SSD drives, Two SATA hard disks
Certainly worth a try, but I find that I can create the symbolic link without referencing the drive letter, but Windows simply inserts the letter in the Target path. In other words, the "\" is a nice shorthand when running the mklink command but does not get rid of the absolute path, including the drive letter, that is assigned to the link.

Interesting. I use Far Manager to create my symbolic links instead of `mklink` command. And Far Manager creates symbolic links with relative paths without any problems at all.

P.S. I just tried doing this from command line with `mklink` and this command

Code:
mklink /D TestLink \Test

successfully created a symbolic link `TestLink` to directory `\Test` without adding a drive letter.

However, I tried this on Windows 10. Is Windows 7 different in this regard?

P.P.S. This post on Superuser suggests that it has always been like that. I don't know why your Windows insists on converting relative path to absolute one. Are you sure you are creating a symbolic link and not a directory junction?
 

My Computer My Computer

At a glance

Windows 7 Pro x64
Computer type
PC/Desktop
OS
Windows 7 Pro x64
Sorry if I have been unclear. I am not disputing that the command syntax you used works:

mklink /d testlink \test

works just fine. But your use of the "\" without the drive letter is little more than a shorthand for running the command.

After creating your link, look at its properties in Windows Explorer. You will notice that Windows has inserted the drive letter. Furthermore, unlike shortcuts, users are not allowed to edit the Target area of the link.
 

My Computer My Computer

At a glance

TXIntell(R) Core(TM) i5-2400 CPU 3.10 GHz 3.30 GHz16GBNone
Computer type
PC/Desktop
Computer Manufacturer/Model Number
Custom Build
OS
TX
CPU
Intell(R) Core(TM) i5-2400 CPU 3.10 GHz 3.30 GHz
Motherboard
Gigabyte GA-Z68MA-D2H-B3
Memory
16GB
Graphics Card(s)
None
Hard Drives
Two SSD drives, Two SATA hard disks
Sorry if I have been unclear. I am not disputing that the command syntax you used works:

mklink /d testlink \test

works just fine. But your use of the "\" without the drive letter is little more than a shorthand for running the command.

Sorry, but that is false. This is not a shorthand. The link will be created specifically with a relative path, exactly as it is specified in the command line (`\test` in this case).

The ability to use relative paths has been one of the "advertised" features of NTFS symbolic links since the moment of their inception.

After creating your link, look at its properties in Windows Explorer. You will notice that Windows has inserted the drive letter.

No, apparently you got misled by the show that Windows Explorer put up for you. It was Windows Explorer who decided to "decipher" the relative path for you in Properties window in an apparent attempt to be "helpful". The link itself does not physically refer to that drive letter. The link stores only relative path, exactly as you specified it in the command line.

Just try it: take a USB drive, create a bunch of relative symbolic links on it and then change the drive letter in Disk Management. See if your symbolic links still work (and they will).

Furthermore, unlike shortcuts, users are not allowed to edit the Target area of the link.

Well... that just one of Windows Explorer's shortcomings, no more, no less. Other tools can edit the path in a symbolic link without any problems (Far Manager, again; also Link Shell Extension).
 

My Computer My Computer

At a glance

Windows 7 Pro x64
Computer type
PC/Desktop
OS
Windows 7 Pro x64
By editing the desktop.ini file I can now make the icons associated with each folder in a portable drive completely independent of the drive letter. You CAN use relative paths for defining the IconResource variable in desktop.ini. This was a very welcome discovery for me, and not many people know this trick, so I was hoping there might be some little-know means of using relative paths with shortcuts and/or symbolic links.

Everyone uses portable drives now. If there is no way to move a drive around without invalidating all the shortcuts & symbolic links then Windows file system architecture is hopelessly antiquated.
 

My Computer My Computer

At a glance

TXIntell(R) Core(TM) i5-2400 CPU 3.10 GHz 3.30 GHz16GBNone
Computer type
PC/Desktop
Computer Manufacturer/Model Number
Custom Build
OS
TX
CPU
Intell(R) Core(TM) i5-2400 CPU 3.10 GHz 3.30 GHz
Motherboard
Gigabyte GA-Z68MA-D2H-B3
Memory
16GB
Graphics Card(s)
None
Hard Drives
Two SSD drives, Two SATA hard disks
My whole life has been symbolic. :)
 

My Computer My Computer

At a glance

Windows 7 Home Premium 32-Bit - Build 7600 SP1Intel Core i3-2120 3.30GhzKingston 4 GB DDR3 1333 mhzAMD Radeon HD6670
Computer type
PC/Desktop
Computer Manufacturer/Model Number
Custom Build
OS
Windows 7 Home Premium 32-Bit - Build 7600 SP1
CPU
Intel Core i3-2120 3.30Ghz
Motherboard
Asus P8Z68-V LX Intel Z68 Socket H2 ATX
Memory
Kingston 4 GB DDR3 1333 mhz
Graphics Card(s)
AMD Radeon HD6670
Sound Card
Sound Blaster Audigy SE 24-Bit
Monitor(s) Displays
Asus VE228
Screen Resolution
1440 X 900
Hard Drives
OCZ Vertex 3 120 GB Sata 3 SSD ==
Kingston SH103/S3 120 G Hyper X 120 GB SSD ==
Western Digital 500 GB Caviar Green 7200 RPM ==
PSU
Corsair CX600M == 600 Watt
Case
NZXT Apollo - Silver with Clear Side Panel
Cooling
Three 120 mm Fans
Keyboard
Microsoft Natural 4000
Mouse
Microsoft Custom Optical 3000
Internet Speed
AT&T Fiber Optic Wireless Network
Antivirus
Microsoft Security Essentials
Browser
Chrome
Other Info
120 mm Blue LED Fan -- Three Blue LED Lazer Light Sticks
Everyone uses portable drives now. If there is no way to move a drive around without invalidating all the shortcuts & symbolic links then Windows file system architecture is hopelessly antiquated.

Well, if you'll keep stubbornly ignoring the fact that NTFS symbolic links have always been able to use relative paths and that relative paths don't invalidate when you "move the drive around", then of course Windows file system architecture might look antiquited to you. But I'm afraid Windows file system architecture is not to blame here.
 

My Computer My Computer

At a glance

Windows 7 Pro x64
Computer type
PC/Desktop
OS
Windows 7 Pro x64
This is not a shorthand. The link will be created specifically with a relative path, exactly as it is specified in the command line (`\test` in this case)

That's good news. Do you know a way to edit a symbolic link and make it relative?

The folder structure on the disks I use are pretty deep and complex, and it is not practical to type lengthy paths in the cmd tool. It would be easier to create them using Windows Explorer enhanced with the Link Shell Extension then modify the links afterwords in the cmd tool to have the relative path.

Is that possible?
 

My Computer My Computer

At a glance

TXIntell(R) Core(TM) i5-2400 CPU 3.10 GHz 3.30 GHz16GBNone
Computer type
PC/Desktop
Computer Manufacturer/Model Number
Custom Build
OS
TX
CPU
Intell(R) Core(TM) i5-2400 CPU 3.10 GHz 3.30 GHz
Motherboard
Gigabyte GA-Z68MA-D2H-B3
Memory
16GB
Graphics Card(s)
None
Hard Drives
Two SSD drives, Two SATA hard disks
AndreyT's solution works perfectly, Pluviosilla, and your claim below is incorrect.
mklink /d testlink \test

works just fine. But your use of the "\" without the drive letter is little more than a shorthand for running the command [mklink /d testlink C:\test].

The given command is not a shorthand for any thing, and the two commands are indeed different. The command,
Code:
mklink /d TestLink C:\Test
will create an absolute path-ed symbolic link to 'C:\Test', whereas the command,
Code:
mklink /d TestLink \Test
will create a relative path-ed symbolic link to the folder 'Test', starting from the root directory of the drive containing the new 'TestLink' symbolic link. This is exactly the command you are after, Pluviosilla. There appears to be only one misunderstanding preventing you from accepting this:
After creating your link, look at its properties in Windows Explorer. You will notice that Windows has inserted the drive letter. Furthermore, unlike shortcuts, users are not allowed to edit the Target area of the link.

As AndreyT has already tried explain to you, what you are observing is just Windows Explorer evaluating the path of the item the symbolic link points to; and it is not an indication of the data stored in the reparse point's buffer, thus the reason why this field cannot be edited.


My whole life has been symbolic.
That's relatively deep.
 

My Computer My Computer

At a glance

Windows 10, Windows 8.1 Pro, Windows 7 Profes...
Computer type
PC/Desktop
OS
Windows 10, Windows 8.1 Pro, Windows 7 Professional, OS X El Capitan
Pyprohly, I totally concede AndreyT's point. He has schooled me in the way this works, and I am grateful. That's why I came to this forum!

But thanks for confirming his information, because I haven't had a chance to test it by moving a drive between computers.

Do you happen to know how to modify the target of an existing symbolic link?

I use *hundreds* of shortcuts buried deeply within complex folder structures. I'd love to create links in Windows Explorer (enhanced with the Link Extension) and then just modify them to use relative instead of absolute paths.

I'm glad to know that mklink does what I want (thanks again), but using the clunky cmd shell to manually create soft links with huge path names is not very practical.
 
Last edited:

My Computer My Computer

At a glance

TXIntell(R) Core(TM) i5-2400 CPU 3.10 GHz 3.30 GHz16GBNone
Computer type
PC/Desktop
Computer Manufacturer/Model Number
Custom Build
OS
TX
CPU
Intell(R) Core(TM) i5-2400 CPU 3.10 GHz 3.30 GHz
Motherboard
Gigabyte GA-Z68MA-D2H-B3
Memory
16GB
Graphics Card(s)
None
Hard Drives
Two SSD drives, Two SATA hard disks
Do you happen to know [of a way] to modify the target of an existing symbolic link?

I use *hundreds* of shortcuts buried deeply within complex folder structures. I'd love to create links in Windows Explorer (enhanced with the Link Extension) and then just modify them to use relative instead of absolute paths.
Automatically processing hundreds of symbolic links isn't going to be nearly as easy as editing hundreds of desktop.ini files to support relative paths.

I Googled thoroughly and carefully in search for a way to edit a symbolic link's properties using Windows' builtin scripts and even sought for a solution through Autoit, but disappointing, I wasn't able to find any simple way to edit the properties of a symbolic link anywhere. There seems to be very little support for soft links across the board.

I'm unable to tell you such a method for editing a symbolic link, Pluviosilla, however, what I can do for you is create a PowerShell script that, instead of editing the symbolic links, creates a new symbolic link that replaces the old link in place, with the new relative path.

(TL;DR: Had to borrow a bit of code for this. I managed to find a function that gets the target directory of a symbolic link. Unfortunately the path that this function returns is an evaluated path to the item which the symbolic link points to, rather than the actual data representing the target item. This shouldn't make much of a difference, only you don't get to see what the old targets of the processed symbolic links were in the script's output.)


th-387133.ps1
Code:
#requires -RunAsAdministrator
# Administrative privileges typically needed to create symbolic links

filter Test-SymLink {
	if (fsutil.exe reparsepoint query $_ | Select-String '^Tag value: Symbolic Link$') {return $_}
}

function Get-ReparsePointTaregetDirectory {
	# reference: http://techibee.com/powershell/read-target-folder-of-a-symlink-using-powershell/1916
	[CmdletBinding()]
	param(
		[string]$Path
	)
	$Definition = @'
	private const int FILE_SHARE_READ = 1;
	private const int FILE_SHARE_WRITE = 2;
	private const int CREATION_DISPOSITION_OPEN_EXISTING = 3;
	private const int FILE_FLAG_BACKUP_SEMANTICS = 0x02000000;
	[DllImport("kernel32.dll", EntryPoint = "GetFinalPathNameByHandleW", CharSet = CharSet.Unicode, SetLastError = true)]
	public static extern int GetFinalPathNameByHandle(IntPtr handle, [In, Out] StringBuilder path, int bufLen, int flags);
	[DllImport("kernel32.dll", EntryPoint = "CreateFileW", CharSet = CharSet.Unicode, SetLastError = true)]
	public static extern SafeFileHandle CreateFile(string lpFileName, int dwDesiredAccess,
	int dwShareMode, IntPtr SecurityAttributes, int dwCreationDisposition, int dwFlagsAndAttributes, IntPtr hTemplateFile);

	public static string GetSymbolicLinkTarget(System.IO.DirectoryInfo symlink)
	{
		SafeFileHandle directoryHandle = CreateFile(symlink.FullName, 0, 2, System.IntPtr.Zero, CREATION_DISPOSITION_OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, System.IntPtr.Zero);
		if(directoryHandle.IsInvalid)
		throw new Win32Exception(Marshal.GetLastWin32Error());
		StringBuilder path = new StringBuilder(512);
		int size = GetFinalPathNameByHandle(directoryHandle.DangerousGetHandle(), path, path.Capacity, 0);
		if (size<0) throw new Win32Exception(Marshal.GetLastWin32Error()); // The remarks section of GetFinalPathNameByHandle mentions the return being prefixed with "\\?\" // More information about "\\?\" here -> http://msdn.microsoft.com/en-us/library/aa365247(v=VS.85).aspx
		if (path[0] == '\\' && path[1] == '\\' && path[2] == '?' && path[3] == '\\') return path.ToString().Substring(4);
		else
		return path.ToString();
	}
'@
	Add-Type -MemberDefinition $Definition -Name Win32 -NameSpace System -UsingNamespace System.Text,Microsoft.Win32.SafeHandles,System.ComponentModel

	[System.Win32]::GetSymbolicLinkTarget($Path)
}

function New-SymLink {
	# https://gallery.technet.microsoft.com/scriptcenter/New-SymLink-60d2531e
	<#
		.SYNOPSIS
			Creates a Symbolic link to a file or directory

		.DESCRIPTION
			Creates a Symbolic link to a file or directory as an alternative to mklink.exe

		.PARAMETER Path
			Name of the path that you will reference with a symbolic link.

		.PARAMETER SymName
			Name of the symbolic link to create. Can be a full path/unc or just the name.
			If only a name is given, the symbolic link will be created on the current directory that the
			function is being run on.

		.PARAMETER File
			Create a file symbolic link

		.PARAMETER Directory
			Create a directory symbolic link

		.NOTES
			Name: New-SymLink
			Author: Boe Prox
			Created: 15 Jul 2013


		.EXAMPLE
			New-SymLink -Path "C:\users\admin\downloads" -SymName "C:\users\admin\desktop\downloads" -Directory

			SymLink                          Target                   Type
			-------                          ------                   ----
			C:\Users\admin\Desktop\Downloads C:\Users\admin\Downloads Directory

			Description
			-----------
			Creates a symbolic link to downloads folder that resides on C:\users\admin\desktop.

		.EXAMPLE
			New-SymLink -Path "C:\users\admin\downloads\document.txt" -SymName "SomeDocument" -File

			SymLink                             Target                                Type
			-------                             ------                                ----
			C:\users\admin\desktop\SomeDocument C:\users\admin\downloads\document.txt File

			Description
			-----------
			Creates a symbolic link to document.txt file under the current directory called SomeDocument.
	#>
	[cmdletbinding(
		DefaultParameterSetName = 'Directory',
		SupportsShouldProcess=$True
	)]
	Param (
		[parameter(Position=0,ParameterSetName='Directory',ValueFromPipeline=$True,
			ValueFromPipelineByPropertyName=$True,Mandatory=$True)]
		[parameter(Position=0,ParameterSetName='File',ValueFromPipeline=$True,
			ValueFromPipelineByPropertyName=$True,Mandatory=$True)]
		[ValidateScript({
			If (Test-Path $_) {$True} Else {
				Throw "`'$_`' doesn't exist!"
			}
		})]
		[string]$Path,
		[parameter(Position=1,ParameterSetName='Directory')]
		[parameter(Position=1,ParameterSetName='File')]
		[string]$SymName,
		[parameter(Position=2,ParameterSetName='File')]
		[switch]$File,
		[parameter(Position=2,ParameterSetName='Directory')]
		[switch]$Directory
	)
	Begin {
		Try {
			$null = [mklink.symlink]
		} Catch {
			Add-Type @"
			using System;
			using System.Runtime.InteropServices;
 
			namespace mklink
			{
				public class symlink
				{
					[DllImport("kernel32.dll")]
					public static extern bool CreateSymbolicLink(string lpSymlinkFileName, string lpTargetFileName, int dwFlags);
				}
			}
"@
		}
	}
	Process {
		#Assume target Symlink is on current directory if not giving full path or UNC
		If ($SymName -notmatch "^(?:[a-z]:\\)|(?:\\\\\w+\\[a-z]\$)") {
			$SymName = "{0}\{1}" -f $pwd,$SymName
		}
		$Flag = @{
			File = 0
			Directory = 1
		}
		If ($PScmdlet.ShouldProcess($Path,'Create Symbolic Link')) {
			Try {
				$return = [mklink.symlink]::CreateSymbolicLink($SymName,$Path,$Flag[$PScmdlet.ParameterSetName])
				If ($return) {
					$object = New-Object PSObject -Property @{
						SymLink = $SymName
						Target = $Path
						Type = $PScmdlet.ParameterSetName
					}
					$object.pstypenames.insert(0,'System.File.SymbolicLink')
					$object
				} Else {
					Throw "Unable to create symbolic link!"
				}
			} Catch {
				Write-warning ("{0}: {1}" -f $path,$_.Exception.Message)
			}
		}
	}
}

Get-ChildItem | Test-SymLink | 
	%{
		$target = Get-ReparsePointTaregetDirectory $_.FullName
		[System.IO.Directory]::Delete($_.FullName)
		if ($?) {New-SymLink -Path ($target -replace '^.:') -SymName $_.FullName -Directory | select `
			@{n='Symlink Location';e={$_.SymLink}}, @{n='New Target';e={$_.Target}}
		}
	}
To begin, open an Elevated PowerShell session, change the current directory to that of your given starting directory by typing a line similar to,
Code:
cd 'C:\some\start\location'
then run the script by entering something like,
Code:
& 'C:\Users\Pyprohly\Downloads\script.ps1'
 

My Computer My Computer

At a glance

Windows 10, Windows 8.1 Pro, Windows 7 Profes...
Computer type
PC/Desktop
OS
Windows 10, Windows 8.1 Pro, Windows 7 Professional, OS X El Capitan
Thanks!

My gosh. It's very kind of you to go to this kind of trouble. I'm very appreciative. I will study your script and try to use it.

I suspected that there might be a Power Shell solution out there somewhere.
 

My Computer My Computer

At a glance

TXIntell(R) Core(TM) i5-2400 CPU 3.10 GHz 3.30 GHz16GBNone
Computer type
PC/Desktop
Computer Manufacturer/Model Number
Custom Build
OS
TX
CPU
Intell(R) Core(TM) i5-2400 CPU 3.10 GHz 3.30 GHz
Motherboard
Gigabyte GA-Z68MA-D2H-B3
Memory
16GB
Graphics Card(s)
None
Hard Drives
Two SSD drives, Two SATA hard disks
Back
Top