如何在复制过程中维护相对符号链接?

如何在复制过程中维护相对符号链接?

我有一个包含一堆相对符号链接的目录结构。例如:

e:\test e:\test\foo\a --> "..\bar"
e:\test\bar\b --> "..\foo"

有没有办法将整个目录从父目录复制到任意位置(备份驱动器...),并保持符号链接的相关性?在上面的例子中,我希望“a”继续指向“上一级,然后下到 \bar”。

我可以使用 xcopy 深度复制每个符号链接的内容,但是这会浪费太多空间。

答案1

您可以使用此 PowerShell 脚本,该脚本已在 Windows 10 上测试:

param ([string]$Source, [string]$Dest)
Add-Type -AssemblyName Microsoft.VisualBasic
Function ReplaceString($text, $original, $replacement) {
    [Microsoft.VisualBasic.Strings]::Replace($text, $original, $replacement, 1, -1, 'Text')
}
$Source = (Resolve-Path $Source).Path
$Dest = (Resolve-Path $Dest).Path
Function CopySubdir($subdirPath) {
    gci $subdirPath -Force | % {
        If (-not $_.PSIsContainer) {
            Copy-Item $_.FullName -Destination (ReplaceString $_.FullName $Source $Dest)
        } ElseIf ($_.LinkType -ne 'SymbolicLink') {
            $newFolderPath = (ReplaceString $_.FullName $Source $Dest)
            mkdir $newFolderPath
            CopySubdir $_.FullName
        }
    }
}
CopySubdir $Source
gci $Source -Recurse -Force | ? {$_.LinkType -eq 'SymbolicLink'} | % {
    $newPath = (ReplaceString $_.FullName $Source $Dest)
    Push-Location $_.Parent.FullName
    $newTarget = (ReplaceString (Resolve-Path $_.Target).Path $Source $Dest)
    Pop-Location
    New-Item -Path $newPath -ItemType SymbolicLink -Target $newTarget
}

将其保存为.ps1文件并按照启用脚本中的说明进行操作PowerShell 标签 wiki。然后您可以从 PowerShell 提示符运行该脚本,如下所示:

.\symcopy.ps1 -Source 'C:\my\source' -Dest 'D:\dest'

它也适用于相对路径,例如.\source

要从正常命令提示符运行:

powershell -command ".\symcopy.ps1 -Source 'C:\my\source' -Dest 'D:\dest'"

目标文件夹应为空文件夹,其内容与源文件夹相同。所有文件和文件夹将照常复制,但所有符号链接将在一切准备就绪后进行检查、调整和复制。

一些注意事项:由于标准用户在正常情况下无法创建符号链接,因此必须以管理员身份运行此脚本。ResourceExists最后阶段可能会抛出一些错误;这些错误并不致命,可以忽略。

答案2

我只是改进了 BenN 的答案,以便它也适用于文件符号链接:

param ([string]$Source, [string]$Dest)

$Source = (Resolve-Path $Source).Path
$Dest = (Resolve-Path $Dest).Path

Add-Type -AssemblyName Microsoft.VisualBasic
Function ReplaceString($text, $original, $replacement) {
    [Microsoft.VisualBasic.Strings]::Replace($text, $original, $replacement, 1, -1, 'Text')
}
Function CopySubdir($subdirPath) {
    dir $subdirPath -Force | % {
        If ($_.LinkType -ne 'SymbolicLink') {
            If (-not $_.PSIsContainer) {
                Copy-Item $_.FullName -Destination (ReplaceString $_.FullName $Source $Dest)
            } Else {
                $newFolderPath = (ReplaceString $_.FullName $Source $Dest)
                mkdir $newFolderPath
                CopySubdir $_.FullName
            }
        }
    }
}
CopySubdir $Source
dir $Source -Recurse -Force | ? {$_.LinkType -eq 'SymbolicLink'} | % {
    $newPath = (ReplaceString $_.FullName $Source $Dest)
    Push-Location $_.Parent.FullName
    $newTarget = (ReplaceString (Resolve-Path $_.Target).Path $Source $Dest)
    Pop-Location
    New-Item -Path $newPath -ItemType SymbolicLink -Target $newTarget
}

相关内容