问题描述
我正在使用 powershell 创建一个存根脚本。我对这个脚本的意图是将过去 x 时间段内未写入的任何数据复制到新位置,检查文件是否已复制,在其原始位置创建“存档”文件的快捷方式,并最终删除旧文件(我还没有写这个部分)。以下是我到目前为止所拥有的。我现在遇到的问题是创建了一个快捷方式,但是所有快捷方式都保存到 C:\Temp 目录中,而不是任何子文件夹中;如果这是原始文件的存储位置。我认为我的问题与 $link 有关,我需要拆分路径并加入它们,但我不确定。非常感谢任何帮助!
# Variables
$Original = "C:\Temp"
$Archive = "\\data\users\Temp"
Get-ChildItem -Path $Original -Recurse |
Where-Object {
$_.LastWriteTime -lt [datetime]::Now.AddMinutes(-1)
} | copy-Item -Destination $Archive -Recurse -force
$sourceFiles = Get-ChildItem $Original -Recurse | Where-Object { $_.LastWriteTime -lt [datetime]::Now.AddMinutes(-1) } | Select Name,Fullname
$destFiles = Get-ChildItem $Archive -Recurse | Select Name,Fullname
$Comparison = Compare-Object $sourceFiles.name $destFiles.name
If ($comparison.sideindicator -ne "<=") {
get-childitem $Archive -Recurse | where { $_.PsIsContainer -eq $false } | ForEach-Object {
$path = '"' + $_.FullName + '"'
$link = $Original + '\' + $_.Basename + '.lnk'
$wshell = New-Object -ComObject WScript.Shell
$shortcut = $wshell.CreateShortcut($link)
$shortcut.TargetPath = $path
$shortcut.Save()
}
}
If ($comparison.sideindicator -eq "<=") {
$comparison.inputobject,$sourceFiles.fullname | Out-File 'C:\ScriptLogs\stubbing.csv' -Force
}
解决方法
这是有问题的代码:
$link = $Original + '\' + $_.Basename + '.lnk'
Basename
只是没有路径的文件名部分,因此 .lnk 文件直接在顶级目录中结束。
你必须像这样使用相对路径:
$RelativePath = [IO.Path]::GetRelativePath( $Archive,$_.FullName )
$link = [IO.Path]::ChangeExtension( "$Original\$RelativePath",'lnk' )
GetRelativePath
需要 .NET 5。要支持旧的 .NET 版本,您可以使用:
Push-Location $Archive
try { $RelativePath = Resolve-Path -Relative $_.FullName }
finally { Pop-Location }
Resolve-Path -Relative
使用当前位置作为基本位置。所以我们使用 Push-Location
来临时改变当前位置。 try
/ finally
用于确保即使在 Resolve-Path
抛出异常的情况下(例如,当您设置 $ErrorActionPreference = 'Stop'
时)也能恢复原始位置。
虽然代码可能像这样工作,但我认为它可以像这样重构:
- 单个
Get-ChildItem
调用来存储要移动到数组中的文件(您当前的$sourceFiles = ...
行) - 一个
foreach
循环遍历此数组以移动每个文件并创建快捷方式。 - 我认为
Compare-Object
甚至没有必要,但也许我遗漏了一些东西。
目前您正在多次迭代相同的目录,这不是很有效并且有很多重复的代码。