Updated check-symlinks.ps1 and sync-dir.ps1

This commit is contained in:
Markus Fleschutz 2025-02-12 13:58:47 +01:00
parent 7ff53658fd
commit 3f0ddc41a0
2 changed files with 23 additions and 23 deletions

View File

@ -1,15 +1,14 @@
<# <#
.SYNOPSIS .SYNOPSIS
Checks symlinks in a folder Checks all symlinks in a folder
.DESCRIPTION .DESCRIPTION
This PowerShell script checks every symbolic link in a folder (including subfolders). This PowerShell script checks all symbolic links in a directory tree. It returns the number of broken symlinks as exit value.
It returns the number of broken symlinks as exit value.
.PARAMETER folder .PARAMETER folder
Specifies the path to the folder Specifies the path to the folder
.EXAMPLE .EXAMPLE
PS> ./check-symlinks C:\Users PS> ./check-symlinks D:\
Checking symlinks at 📂C:\Users including subfolders... Please wait while checking symlinks at: 📂D:\ ...
Found 0 broken symlinks at 📂C:\Users in 60 sec Found 0 broken symlinks at 📂D:\ in 60s.
.LINK .LINK
https://github.com/fleschutz/PowerShell https://github.com/fleschutz/PowerShell
.NOTES .NOTES
@ -19,36 +18,36 @@
param([string]$Folder = "") param([string]$Folder = "")
try { try {
if ($Folder -eq "" ) { $Folder = read-host "Enter the path to the folder" } if ($Folder -eq "" ) { $Folder = Read-Host "Enter the path to the folder" }
$StopWatch = [system.diagnostics.stopwatch]::startNew() $stopWatch = [system.diagnostics.stopwatch]::startNew()
$FullPath = Resolve-Path "$Folder" $fullPath = Resolve-Path "$Folder"
"Checking symlinks at 📂$FullPath including subfolders..." "Please wait while checking symlinks at 📂$fullPath ..."
[int]$NumTotal = [int]$NumBroken = 0 [int]$numTotal = [int]$numBroken = 0
Get-ChildItem $FullPath -recurse | Where { $_.Attributes -match "ReparsePoint" } | ForEach-Object { Get-ChildItem $fullPath -recurse | Where { $_.Attributes -match "ReparsePoint" } | ForEach-Object {
$Symlink = $_.FullName $Symlink = $_.FullName
$Target = ($_ | Select-Object -ExpandProperty Target -ErrorAction Ignore) $Target = ($_ | Select-Object -ExpandProperty Target -ErrorAction Ignore)
if ($Target) { if ($Target) {
$path = $_.FullName + "\..\" + ($_ | Select-Object -ExpandProperty Target) $path = $_.FullName + "\..\" + ($_ | Select-Object -ExpandProperty Target)
$item = Get-Item $path -ErrorAction Ignore $item = Get-Item $path -ErrorAction Ignore
if (!$item) { if (!$item) {
$NumBroken++ $numBroken++
"Symlink $Symlink to: $Target seems broken (#$NumBroken)" "Broken symlink #$($numBroken) at $Symlink linking to: $Target"
} }
} }
$NumTotal++ $numTotal++
} }
[int]$Elapsed = $StopWatch.Elapsed.TotalSeconds [int]$elapsed = $stopWatch.Elapsed.TotalSeconds
if ($NumTotal -eq 0) { if ($numTotal -eq 0) {
"✅ No symlink found at 📂$FullPath in $Elapsed sec" "✅ No symlink found at 📂$fullPath in $($elapsed)s."
} elseif ($NumBroken -eq 1) { } elseif ($numBroken -eq 1) {
"✅ Found $NumBroken broken symlink at 📂$FullPath in $Elapsed sec" "✅ Found $numBroken broken symlink at 📂$fullPath in $($elapsed)s ($numTotal symlinks in total)."
} else { } else {
"✅ Found $NumBroken broken symlinks at 📂$FullPath in $Elapsed sec" "✅ Found $numBroken broken symlinks at 📂$fullPath in $($elapsed)s ($numTotal symlinks in total)."
} }
exit $NumBroken exit $numBroken
} catch { } catch {
"⚠️ Error in line $($_.InvocationInfo.ScriptLineNumber): $($Error[0])" "⚠️ Error in line $($_.InvocationInfo.ScriptLineNumber): $($Error[0])"
exit 1 exit 1

View File

@ -27,9 +27,10 @@ try {
$stopWatch = [system.diagnostics.stopwatch]::startNew() $stopWatch = [system.diagnostics.stopwatch]::startNew()
"⏳ Please wait while syncing content from 📂$sourcePath to 📂$targetPath ..." "⏳ Please wait while syncing content from 📂$sourcePath to 📂$targetPath ..."
& robocopy.exe $sourcePath $targetPath /MIR /FFT /NJH /NDL /NFL /NP /NS & robocopy.exe $sourcePath $targetPath /MIR /SL /FFT /NJH /NDL /NFL /NP /NS
# #
# /MIR = mirror a directory tree # /MIR = mirror a directory tree
# /SL = copy Symbolic Links as links instead of as the link targets
# /FFT = assume FAT file times (2-second granularity) # /FFT = assume FAT file times (2-second granularity)
# /NJH = no job header # /NJH = no job header
# /NDL = no directory list (don't log directory names) # /NDL = no directory list (don't log directory names)