如何创建相对符号链接powershell方式?

时间:2017-02-28 16:18:00

标签: powershell file-io

在powershell 5.1中创建 相对 符号链接并不是那么简单。 New-Item未按预期工作。下面列出了一些方法。我错过了什么吗?

所有示例的示例设置:

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

示例1:是否按预期工作

#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

示例2:是否按预期工作

#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

Sample3:按预期工作

#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")

Sample4:按预期工作

#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

编辑:Sample3已更新为unicode api entry和GetLastError

4 个答案:

答案 0 :(得分:1)

从 pwsh 7.1.X sample1 开始按预期工作:

#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

答案 1 :(得分:0)

您可以尝试将此功能添加到$ 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
}

答案 2 :(得分:0)

我认为,如果将目标参数转换为System.IO.Fileinfo,那么您也将在第一个版本中获得所需的结果。

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

答案 3 :(得分:-1)

尝试这样的事情:

λ :t entityValue . entityValue 
entityValue . entityValue
  :: (DSLEntity r1 (LangL r2 (ValueOf a)), DSLEntity r2 a) =>
     a -> LangL r1 (ValueOf a)