Creating hard and soft links using PowerShell

PowershellSymlink

Powershell Problem Overview


Can PowerShell 1.0 create hard and soft links analogous to the Unix variety?

If this isn't built in, can someone point me to a site that has a ps1 script that mimics this?

This is a necessary function of any good shell, IMHO. :)

Powershell Solutions


Solution 1 - Powershell

Windows 10 (and Powershell 5.0 in general) allows you to create symbolic links via the New-Item cmdlet.

Usage:

New-Item -Path C:\LinkDir -ItemType SymbolicLink -Value F:\RealDir

Or in your profile:

function make-link ($target, $link) {
	New-Item -Path $link -ItemType SymbolicLink -Value $target
}

Turn on Developer Mode to not require admin privileges when making links with New-Item:

enter image description here

Solution 2 - Powershell

You can call the mklink provided by cmd, from PowerShell to make symbolic links:

cmd /c mklink c:\path\to\symlink c:\target\file

You must pass /d to mklink if the target is a directory.

cmd /c mklink /d c:\path\to\symlink c:\target\directory

For hard links, I suggest something like Sysinternals Junction.

Solution 3 - Powershell

Add "pscx" module

No, it isn't built into PowerShell. And the mklink utility cannot be called on its own on Windows Vista/Windows 7 because it is built directly into cmd.exe as an "internal command".

You can use the PowerShell Community Extensions (free). There are several cmdlets for reparse points of various types:

  • New-HardLink,
  • New-SymLink,
  • New-Junction,
  • Remove-ReparsePoint
  • and others.

Solution 4 - Powershell

In Windows 7, the command is

fsutil hardlink create new-file existing-file

PowerShell finds it without the full path (c:\Windows\system32) or extension (.exe).

Solution 5 - Powershell

New-Symlink:

Function New-SymLink ($link, $target)
{
	if (test-path -pathtype container $target)
	{
		$command = "cmd /c mklink /d"
	}
	else
	{
		$command = "cmd /c mklink"
	}

	invoke-expression "$command $link $target"
}

Remove-Symlink:

Function Remove-SymLink ($link)
{
	if (test-path -pathtype container $link)
	{
		$command = "cmd /c rmdir"
	}
	else
	{
		$command = "cmd /c del"
	}

	invoke-expression "$command $link"
}

Usage:

New-Symlink "c:\foo\bar" "c:\foo\baz"
Remove-Symlink "c:\foo\bar"

Solution 6 - Powershell

Try junction.exe

The Junction command line utility from SysInternals makes creating and deleting junctions easy.

Further reading

  • MS Terminology: soft != symbolic
    Microsoft uses "soft link" as another name for "junction".
    However: a "symbolic link" is something else entirely.
    See MSDN: Hard Links and Junctions in Windows.
    (This is in direct contradiction to the general usage of those terms where "soft link" and "symbolic link" ("symlink") DO mean the same thing.)

Solution 7 - Powershell

I combined two answers (@bviktor and @jocassid). It was tested on Windows 10 and Windows Server 2012.

function New-SymLink ($link, $target)
{
    if ($PSVersionTable.PSVersion.Major -ge 5)
    {
        New-Item -Path $link -ItemType SymbolicLink -Value $target
    }
    else
    {
        $command = "cmd /c mklink /d"
        invoke-expression "$command ""$link"" ""$target"""
    }
}

Solution 8 - Powershell

You can use this utility:

c:\Windows\system32\fsutil.exe create hardlink

Solution 9 - Powershell

I wrote a PowerShell module that has native wrappers for MKLINK. https://gist.github.com/2891103

Includes functions for:

  • New-Symlink
  • New-HardLink
  • New-Junction

Captures the MKLINK output and throws proper PowerShell errors when necessary.

Solution 10 - Powershell

Actually, the Sysinternals junction command only works with directories (don't ask me why), so it can't hardlink files. I would go with cmd /c mklink for soft links (I can't figure why it's not supported directly by PowerShell), or fsutil for hardlinks.

If you need it to work on Windows XP, I do not know of anything other than Sysinternals junction, so you might be limited to directories.

Solution 11 - Powershell

I found this the simple way without external help. Yes, it uses an archaic DOS command but it works, it's easy, and it's clear.

$target = cmd /c dir /a:l | ? { $_ -match "mySymLink \[.*\]$" } | % `
{
    $_.Split([char[]] @( '[', ']' ), [StringSplitOptions]::RemoveEmptyEntries)[1]
}

This uses the DOS dir command to find all entries with the symbolic link attribute, filters on the specific link name followed by target "[]" brackets, and for each - presumably one - extracts just the target string.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionMike TView Question on Stackoverflow
Solution 1 - PowershelljocassidView Answer on Stackoverflow
Solution 2 - PowershellJason R. CoombsView Answer on Stackoverflow
Solution 3 - PowershellKeith HillView Answer on Stackoverflow
Solution 4 - PowershellquigiView Answer on Stackoverflow
Solution 5 - PowershellbviktorView Answer on Stackoverflow
Solution 6 - PowershellnotandyView Answer on Stackoverflow
Solution 7 - Powershellmhenry1384View Answer on Stackoverflow
Solution 8 - PowershellCheesoView Answer on Stackoverflow
Solution 9 - PowershelljoshuapoehlsView Answer on Stackoverflow
Solution 10 - PowershellanonView Answer on Stackoverflow
Solution 11 - PowershellStevenView Answer on Stackoverflow