我有一个包含一堆相对符号链接的目录结构。例如:
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
}