How to create relative symlink powershell?

Creating relative symbolic links in powershell 5.1 is not so easy. New-Item does not work as expected. Listed below are some approaches. Did I miss something?

Setting example for all examples:

 mkdir C:\Temp\foo -ErrorAction SilentlyContinue 'sample contents' > C:\Temp\foo\foo.txt cd C:\Temp 

Example1: does not work

 #new ps5 Item cmdlets (https://msdn.microsoft.com/en-us/powershell/wmf/5.0/feedback_symbolic) are not working well with relative paths #C:\Temp\foo and C:\Temp\foo\foo.txt are returned $fld = New-Item -ItemType SymbolicLink -Name 'bar' -Target '.\foo' $fl = New-Item -ItemType SymbolicLink -Name 'bar.txt' -Target '.\foo\foo.txt' $fld.Target $fl.Target 

Sample 2: does not work

 #Powershell community extensions #same problem - paths are created as absolute: C:\Temp\foo C:\Temp\foo\foo.txt $fld = New-Symlink 'c:\Temp\bar' '.\foo' $fl = New-Symlink 'c:\Temp\bar.txt' '.\foo\foo.txt' $fld.Target $fl.Target 

Sample 3: works as expected

 #API call CreateSymbolicLink as per https://gallery.technet.microsoft.com/scriptcenter/new-symlink-60d2531e #.\foo and .\foo\foo.txt are returned Add-Type -MemberDefinition @' [DllImport("kernel32.dll", EntryPoint = "CreateSymbolicLinkW", CharSet = CharSet.Unicode, SetLastError = true)] public static extern bool CreateSymbolicLink(string lpSymlinkFileName, string lpTargetFileName, int dwFlags); public static DirectoryInfo CreateSymbolicLinkToFolder(string lpSymlinkFileName, string lpTargetFileName) { bool res = CreateSymbolicLink(lpSymlinkFileName, lpTargetFileName, 1); if (!res) { throw new Win32Exception(Marshal.GetLastWin32Error()); } return (new DirectoryInfo(lpSymlinkFileName)); } public static FileInfo CreateSymbolicLinkToFile(string lpSymlinkFileName, string lpTargetFileName) { bool res = CreateSymbolicLink(lpSymlinkFileName, lpTargetFileName, 0); if (!res) { throw new Win32Exception(Marshal.GetLastWin32Error()); } return (new FileInfo(lpSymlinkFileName)); } '@ -Name Win32 -NameSpace System -UsingNamespace System.ComponentModel, System.IO [Win32]::CreateSymbolicLinkToFolder("c:\Temp\bar", ".\foo") [Win32]::CreateSymbolicLinkToFile("c:\Temp\bar.txt", ".\foo\foo.txt") 

Sample 4: works as expected

 #using mklink from cmd produces correct relative paths #.\foo and .\foo\foo.txt are returned cmd /c mklink /d "c:\Temp\bar" ".\foo" cmd /c mklink "c:\Temp\bar.txt" ".\foo\foo.txt" (Get-Item "c:\Temp\bar").Target (Get-Item "c:\Temp\bar.txt").Target 

Edit: Sample3 has been updated to write in unicode api and GetLastError

+5
source share
2 answers

You can try adding this function to your $ PROFILE.

 Function SymbolicLink-Add { [CmdLetBinding( )] Param ( [string] $File, [string] $SymbolicLinkFolder ) $LinkFile = (Get-Item $File) if ( $false -eq $LinkFile.Exists ) { return "Cannot create symbolic link file does not exist: [$File]" } if ( $false -eq ( Test-Path $SymbolicLinkFolder ) ) { New-Item -Type Directory -Path $SymbolicLinkFolder -ErrorAction Stop } New-Item -ItemType SymbolicLink -Path $SymbolicLinkFolder -Name $LinkFile.Name -Value $LinkFile } 
0
source

I think that if you convert the target argument to System.IO.Fileinfo, you will get the desired result in the first version.

  New-Item -ItemType SymbolicLink -Name "bar" -target ([System.IO.FileInfo]"./foo") 
0
source

Source: https://habr.com/ru/post/1264842/


All Articles