用于复制旧文件并创建快捷方式的 Powershell 脚本

问题描述

我正在使用 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 甚至没有必要,但也许我遗漏了一些东西。

目前您正在多次迭代相同的目录,这不是很有效并且有很多重复的代码。