324

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. :)

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Mike T
  • 3,696
  • 4
  • 21
  • 21
  • 11
    Windows 10 users see http://stackoverflow.com/a/34905638/195755 . Windows 10 it **is** built-in. Copy/Paste: `New-Item -Type ` and press tab to cycle through the options. `Hardlink`, `SymbolicLink`, and `Junction` appear for me. Works Win 10, Server 2016+, or older OS with Powershell 5.0+ installed via Windows Management Framework 5.0+. – yzorg Sep 28 '16 at 21:01
  • 3
    I can't find decent MSDN/TechNet documentation for `New-Item -Type HardLink` nor `New-Item -Type SymbolicLink`. New-Item docs link to `help about_Providers`, it suggests you read help for each provider (which isn't linked). But if you google it there is plenty of buzz in the PowerShell community around `New-Item -Type HardLink`. It looks like the PowerShell engineering team has come up with **provider** extension points that stump the docs team. – yzorg Sep 28 '16 at 21:06
  • 4
    **`WARNING!`** -- While it is very easy to create *hardlinks*, it may be quite a challenge to remove them securely. That is because the tools are not easily available in native Powershell while Windows like to lock file access and keep files in memory (thus not always removable without a reboot.) Please see my post [here](https://superuser.com/a/1590780/). – not2qubit Oct 05 '20 at 01:26
  • Can we consider removing the version 1.0 from the question? With the number of votes I'd bet 99.9% of folks hitting this page are NOT don't care about 1.0. – yzorg Mar 08 '23 at 16:10

11 Answers11

422

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

Martin Schneider
  • 14,263
  • 7
  • 55
  • 58
jocassid
  • 4,429
  • 1
  • 13
  • 6
  • 3
    This link is now broken due to MS rearranging documentation. I found a current working link at https://technet.microsoft.com/en-us/library/hh849795.aspx – Aaron Thomas Jul 19 '16 at 15:55
  • 3
    New-Item -Path C:\LinkDir -ItemType SymbolicLink -Value F:\RealDir – Daniel Fisher lennybacon Aug 16 '16 at 08:43
  • 13
    since Windows v1703, mklink allows creating symlinks without account elevation, if Developer mode is enabled in Settings, New-Item doesn't. Hopefully in next update. – papo Jun 29 '17 at 01:46
  • Fascinating. So this is quite distinct from an Explorer `.lnk` shortcut. In explorer, a shortcut and symlink of the same name display side by side as if nothing was amiss. Their behaviors are subtly different; following the symlink shows the absolute path in the Explorer bar. Following the shortcut treats it as if the symlink parent dir is the true parent. – BaseZen Oct 18 '18 at 16:03
  • 2
    With the [accepted answer](https://stackoverflow.com/questions/894430/creating-hard-and-soft-links-using-powershell/5549583#5549583), I was able to use relative paths, which wasn't the case with the `New-Item` commandlet. – Dave F Apr 21 '19 at 02:19
  • 7
    New-Item allows an `-ItemType` of `HardLink` for a file and `Junction` for a directory. These do not require developer mode or admin privileges. – Cpt.Whale Oct 11 '19 at 16:55
  • Also note that this solution works on Linux system too. `New-Item -Path /opt/link -ItemType SymbolicLink -Value /usr/local/bin` – minus one Feb 10 '21 at 12:35
  • I can't turn on developer mode for my work laptop. – yzorg Mar 08 '23 at 16:07
304

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.

Dave F
  • 1,837
  • 15
  • 20
Jason R. Coombs
  • 41,115
  • 10
  • 83
  • 93
  • 32
    If you have a powershell profile, you can also make a quick function `function mklink { cmd /c mklink $args }` – Joe Young Nov 06 '11 at 02:19
  • 14
    and if you want to make a directory link, the command will be something like { cmd /c mklink /D "toDir" fromDir } – DavidDraughn Mar 28 '12 at 15:38
  • 10
    adding the /H parameter to mklink will create a hard link without the need for a third party program like Sysinternals Junction. – Fopedush Dec 19 '12 at 01:40
  • 6
    I think jocassid has the better answer. IMHO, We should try to teach how to USE PowerShell, not use exploits and hacks through cmd.exe. – Cameron Oakenleaf Sep 23 '17 at 05:10
  • @CameronOakenleaf I agree whole-heartedly. – Jason R. Coombs Sep 24 '17 at 14:54
  • it won't work in PowerShell when trying to access symbolic link as cd c:\path\to\symlink. PowerShell cmdlet: NewItem -Path c:\link -ItemType SymbolicLink -Value D:\target\file works – Serge V. Dec 30 '17 at 14:24
  • 3
    @SergeVoloshenko It [sure does](https://gist.github.com/fa4278b3738c8f0b0680aaf9237b6f47). True, using `New-Item` [does detect if the target is a directory](https://gist.github.com/d6b38f78a078afe8c734226d6040b3d7), but `New-Item` [will fail if the target does not exist](https://gist.github.com/3b75396b4fc51f863a9434cec446cd95) whereas [mklink will create the symbolic link regardless](https://gist.github.com/9f2ea76f1539163b45c4e033a4f67d2a). – Jason R. Coombs Dec 31 '17 at 18:38
  • and using /j parameter instead of /h, makes a directory junction where the source folder (link) will always appear as the source folder to all applications. Using /d entering via the source folder (link) will then jump to and appear as the real target folder, which is a problem if storing paths shared in team environments. – Deano Oct 16 '19 at 05:20
47

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.
Community
  • 1
  • 1
Keith Hill
  • 194,368
  • 42
  • 353
  • 369
  • 1
    Good try. Though if you want to run XP or W2K3 server in either x32 or x64, New-Symlink dosen't work. In XP it will politely tell you that you should be running Vista for this command. In W2K3 server, it flat out breaks. – Mike T May 21 '09 at 19:55
  • 1
    That's because XP doesn't support symlinks. That's a feature new to Vista. I believe that W2K3 server doesn't support symlinks either. You have to step up to W2K8 server to get symlink support. I'll look into why new-symlink is bombing on W2k3, it should error with a similar message to XP. – Keith Hill May 21 '09 at 21:09
  • I tried new-junction and that will work for me. Too bad the link functionality doesn't degrade to junctions in XP and W2K3 – Mike T May 21 '09 at 22:06
  • on further use of new-junction... I get a junction to the new parse point. However ls (or get-childitem) errors stating that.."The filename, directory name, or volume label syntax is incorrect" If I try and enter a subdirectory from there. – Mike T May 21 '09 at 23:24
  • 3
    Windows 10 users see answer http://stackoverflow.com/a/34905638/195755 . Windows 10 it *is* built-in. Copy/Paste: `New-Item -Type ` and press tab to cycle through the options. `Hardlink`, `SymbolicLink`, and `Junction` appear for me. Works Win 10, Server 2016+, or older OS with Powershell 5.0 installed via Windows Management Framework 5.0+. – yzorg Sep 28 '16 at 20:57
  • This answer is no longer correct, please see @jocassid's answer. – rsmith54 Jul 23 '19 at 23:18
  • Answer kinda broken now (2019). Because by now PSCX commands clash with native PowerShell commands. And PSCX requires workarounds to even install. => https://github.com/Pscx/Pscx/issues/23 (And that ticket has been unfixed since 2017. So I don't expect a real fix anytime soon.) – StackzOfZtuff Oct 04 '19 at 10:15
  • Agreed. **Ten** years ago this made sense but yeah, PowerShell has finally added built-in commands for this functionality. :-) – Keith Hill Oct 06 '19 at 18:01
28

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).

quigi
  • 281
  • 3
  • 2
  • 1
    `fsutil hardlink` requires `new-file` and `existing-file` to be on the same drive. If that matters to you, use cmd's `mklink /c` instead. – mopsled Jan 29 '15 at 19:54
  • 13
    @mopsled Hardlinks, by definition, must be on the same volume as the target, this is not a limitation specific to `fsutil` (or Windows for that matter) – Dev Feb 23 '15 at 15:35
  • is there an equivalent for "soft" symlinks and junctions? – jshall Dec 08 '15 at 01:40
  • Worked also on a Windows10 system. – FooF Feb 21 '19 at 04:09
15

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"
bviktor
  • 1,356
  • 13
  • 14
  • 2
    Windows 10 users see http://stackoverflow.com/a/34905638/195755 . Windows 10 it *is* built-in. Copy/Paste: `New-Item -Type ` and press tab to cycle through the options. `Hardlink`, `SymbolicLink`, and `Junction` appear for me. Works Win 10, Server 2016+, or older OS with Powershell 5.0 installed via Windows Management Framework 5.0+. – yzorg Sep 28 '16 at 20:52
  • Or if the file name contains them. – Chris Charabaruk Sep 30 '17 at 02:32
12

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.)
Community
  • 1
  • 1
notandy
  • 3,330
  • 1
  • 27
  • 35
  • The use of this utility correctly allows me to junction another directory and traverse it's subdirectories successfully. All in XP and W2K3. Just add the exe to a directory in your PATH and call it like normal. – Mike T May 21 '09 at 23:31
  • I don't think you can use junction.exe to create symbolic links. – Jason R. Coombs Apr 05 '11 at 09:04
  • 3
    It´s better to use `mklink` which is shipped with Windows. *If* you have a Windows version which it is shipped with. – Deleted Jul 30 '12 at 17:07
7

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"""
    }
}
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
mhenry1384
  • 7,538
  • 5
  • 55
  • 74
6

You can use this utility:

c:\Windows\system32\fsutil.exe create hardlink
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Cheeso
  • 189,189
  • 101
  • 473
  • 713
3

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.

joshuapoehls
  • 32,695
  • 11
  • 50
  • 61
1

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.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
anon
  • 311
  • 3
  • 3
-2

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.

Steven
  • 1