I am working on creating a stubbing script using powershell. My intentions for this script is to copy any data that hasn't been written to in the past x time period to a new location, check that the file copied, create a shortcut to the "archived" file in it's original location, and eventually delete the old file (I haven't written this section yet). Below is what I have so far. The issue I am having now is that a shortcut is created however all of the shortcuts are saved to the C:\Temp directory and not in any subfolders; if that is where the original file was stored. I think my issue is with $link and I need to split the path's and join them but I am not sure. Any assistance is greatly appreciated!
# 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
}
This is the problematic code:
Basename
is only the filename portion without the path, so the .lnk files end up directly in the top-level directory.You have to use the relative path like this:
This requires .NET 5 for
GetRelativePath
. To support older .NET versions you can use:Resolve-Path -Relative
uses the current location as the base base. So we usePush-Location
to temporarily change the current location. Thetry
/finally
is used to ensure restoring of the original location even in caseResolve-Path
throws an exception (e. g. when you have set$ErrorActionPreference = 'Stop'
).Although the code might work like this, I think it could be refactored like this:
Get-ChildItem
call to store the files to be moved into an array (your current$sourceFiles = ...
line)foreach
loop over this array to move each file and create the shortcut.Compare-Object
isn't even necessary, but maybe I'm missing something.Currently you are iterating over the same directories multiple times, which isn't very efficient and a lot of duplicate code.