Hi, da es mir auf den Senkel ging, die umbenannten Dateien in die Betreutenordner manuell zu ziehen (das kann schon nach einer Woche schon Zeit in Anspruch nehmen)
Habe ich ein Powershellskript gebaut. Also eine kleine Datei im Überordner, ein Mausklick und alles ist einsortiert. Es sei denn es lässt sich keinem Namen zuordnen, dann bleibt es liegen.
Also wer das auch gern möchte:
eine Textdatei öffnen, die in "PDF-sortieren-neutral.ps1" nach einfügen dieses codes umbenennen:
Zitat:
# PDF-Sortierer NEUTRAL fuer Betreutenordner
# Universell einsetzbare Version ohne personenbezogene Sonderregeln.
#
# Verwendung:
# - Diese Datei und die zugehoerige .cmd in den Hauptordner legen,
# in dem die Betreuten-Unterordner und die unsortierten PDFs liegen.
# - Dann PDF-sortieren-neutral.cmd doppelklicken.
#
# Verhalten:
# - Unterordner werden bei jedem Start automatisch eingelesen.
# - Nur PDF-Dateien direkt im gleichen Ordner werden verarbeitet.
# - Verschoben wird nur bei genau EINER eindeutigen Zuordnung.
# - Bei keinem oder mehreren Treffern bleibt die Datei liegen.
# - Vorhandene Zieldateien werden niemals ueberschrieben.
# - Ordner mit "Beendete" im Namen werden ignoriert.
# - Protokoll: PDF-Sortierung.log
$ErrorActionPreference = "Stop"
$Basis = Split-Path -Parent $MyInvocation.MyCommand.Path
$LogDatei = Join-Path $Basis "PDF-Sortierung.log"
# ------------------------------------------------------------
# OPTIONALE SONDERREGELN
#
# Standardmaessig leer.
# Nur verwenden, wenn ein in PDFs verwendeter Name NICHT aus dem
# Ordnernamen abgeleitet werden kann.
#
# Beispiel:
# $Sonderregeln = @{
# "mustermannalt" = "Mustermann, Erika"
# }
# ------------------------------------------------------------
$Sonderregeln = @{}
function Normalisieren([string]$Text) {
if ([string]::IsNullOrWhiteSpace($Text)) { return "" }
$t = $Text.ToLowerInvariant()
$t = $t.Replace("ä","ae").Replace("ö","oe").Replace("ü" ,"ue").Replace("ß","ss")
return ($t -replace '[^a-z0-9]', '')
}
function DateiToken([string]$DateinameOhneEndung) {
$t = $DateinameOhneEndung.ToLowerInvariant()
$t = $t.Replace("ä","ae").Replace("ö","oe").Replace("ü" ,"ue").Replace("ß","ss")
return @(
($t -split '[^a-z0-9]+') |
Where-Object { -not [string]::IsNullOrWhiteSpace($_) }
)
}
function OrdnerInfo($Ordner) {
$Name = $Ordner.Name
# Beispiel: "Mustermann, Erika"
if ($Name -match '^([^,]+),\s*(.+)$') {
$Nachname = Normalisieren $Matches[1]
$Vorname = Normalisieren $Matches[2]
$StarkeAliase = @()
if ($Nachname -and $Vorname) {
$StarkeAliase += ($Nachname + $Vorname.Substring(0,1))
$StarkeAliase += ($Nachname + $Vorname)
}
return [PSCustomObject]@{
Ordner = $Ordner
Basisname = $Nachname
StarkeAliase = @($StarkeAliase | Select-Object -Unique)
}
}
# Beispiel: "MustermannE", "MeierK"
# Ein einzelner Grossbuchstabe am Ende wird als Initiale interpretiert.
if ($Name -match '^(.+?)([A-ZÄÖÜ])$') {
$Stamm = Normalisieren $Matches[1]
$Initiale = Normalisieren $Matches[2]
return [PSCustomObject]@{
Ordner = $Ordner
Basisname = $Stamm
StarkeAliase = @((Normalisieren $Name), ($Stamm + $Initiale)) | Select-Object -Unique
}
}
# Einfacher Ordnername, z.B. "Mustermann"
$Basisname = Normalisieren $Name
return [PSCustomObject]@{
Ordner = $Ordner
Basisname = $Basisname
StarkeAliase = @($Basisname)
}
}
function Schreibe-Log([string]$Text) {
$Zeit = Get-Date -Format "yyyy-MM-dd HH:mm:ss"
Add-Content -LiteralPath $LogDatei -Value "[$Zeit] $Text" -Encoding UTF8
}
Add-Content -LiteralPath $LogDatei -Value "" -Encoding UTF8
Schreibe-Log "=== Start PDF-Sortierung neutral ==="
$Ordner = @(
Get-ChildItem -LiteralPath $Basis -Directory |
Where-Object { $_.Name -notmatch '(?i)Beendete' }
)
$Infos = @()
foreach ($O in $Ordner) {
$Infos += OrdnerInfo $O
}
# Zaehlen, wie oft ein Nachname/Basisname vorkommt.
# Ein reiner Nachname wird nur dann automatisch verwendet,
# wenn er unter den aktiven Ordnern genau einmal vorkommt.
$BasisHaeufigkeit = @{}
foreach ($I in $Infos) {
if ($I.Basisname) {
if (-not $BasisHaeufigkeit.ContainsKey($I.Basisname)) {
$BasisHaeufigkeit[$I.Basisname] = 0
}
$BasisHaeufigkeit[$I.Basisname]++
}
}
$PDFs = @(Get-ChildItem -LiteralPath $Basis -File -Filter "*.pdf")
$Verschoben = 0
$KeinTreffer = 0
$Mehrdeutig = 0
$SchonDa = 0
$Fehler = 0
foreach ($Datei in $PDFs) {
try {
$Tokens = @(DateiToken $Datei.BaseName)
$Treffer = @()
# 1. Optionale Sonderregeln
foreach ($Suchbegriff in $Sonderregeln.Keys) {
$SuchNorm = Normalisieren $Suchbegriff
if ($Tokens -contains $SuchNorm) {
$Zielname = $Sonderregeln[$Suchbegriff]
$Zielordner = @($Ordner | Where-Object { $_.Name -eq $Zielname })
if ($Zielordner.Count -eq 1) {
$Treffer += $Zielordner[0]
}
}
}
# 2. Starke Aliase wie "mustermanne"
foreach ($I in $Infos) {
foreach ($Alias in @($I.StarkeAliase)) {
if ($Alias -and ($Tokens -contains $Alias)) {
$Treffer += $I.Ordner
break
}
}
}
# 3. Reiner Nachname nur, wenn eindeutig vorhanden
foreach ($I in $Infos) {
$Basisname = $I.Basisname
if (
$Basisname -and
$Basisname.Length -ge 4 -and
($Tokens -contains $Basisname) -and
$BasisHaeufigkeit[$Basisname] -eq 1
) {
$Treffer += $I.Ordner
}
}
$TrefferArray = @($Treffer | Sort-Object FullName -Unique)
if ($TrefferArray.Count -eq 1) {
$Ziel = Join-Path $TrefferArray[0].FullName $Datei.Name
if (Test-Path -LiteralPath $Ziel) {
$SchonDa++
Schreibe-Log "NICHT VERSCHOBEN - Zieldatei existiert bereits: '$($Datei.Name)' -> '$($TrefferArray[0].Name)'"
}
else {
Move-Item -LiteralPath $Datei.FullName -Destination $Ziel
$Verschoben++
Schreibe-Log "VERSCHOBEN: '$($Datei.Name)' -> '$($TrefferArray[0].Name)'"
}
}
elseif ($TrefferArray.Count -gt 1) {
$Mehrdeutig++
$Namen = ($TrefferArray.Name -join ", ")
Schreibe-Log "MEHRDEUTIG - Datei bleibt liegen: '$($Datei.Name)' -> $Namen"
}
else {
# Mehrfach vorhandener Nachname ohne Initiale/Vorname
$Moegliche = @()
foreach ($I in $Infos) {
$Basisname = $I.Basisname
if (
$Basisname -and
($Tokens -contains $Basisname) -and
$BasisHaeufigkeit[$Basisname] -gt 1
) {
$Moegliche += $I.Ordner
}
}
$Moegliche = @($Moegliche | Sort-Object FullName -Unique)
if ($Moegliche.Count -gt 1) {
$Mehrdeutig++
$Namen = ($Moegliche.Name -join ", ")
Schreibe-Log "MEHRDEUTIG - Datei bleibt liegen: '$($Datei.Name)' -> $Namen"
}
else {
$KeinTreffer++
Schreibe-Log "KEIN TREFFER - Datei bleibt liegen: '$($Datei.Name)'"
}
}
}
catch {
$Fehler++
Schreibe-Log "FEHLER bei '$($Datei.Name)': $($_.Exception.Message)"
}
}
Schreibe-Log "Ergebnis neutral: $Verschoben verschoben | $KeinTreffer ohne Treffer | $Mehrdeutig mehrdeutig | $SchonDa Ziel schon vorhanden | $Fehler Fehler"
Schreibe-Log "=== Ende PDF-Sortierung neutral ==="
Write-Host ""
Write-Host "PDF-Sortierung abgeschlossen."
Write-Host ""
Write-Host "Verschoben: $Verschoben"
Write-Host "Ohne Treffer: $KeinTreffer"
Write-Host "Mehrdeutig: $Mehrdeutig"
Write-Host "Ziel schon vorhanden: $SchonDa"
Write-Host "Fehler: $Fehler"
Write-Host ""
Write-Host "Protokoll: $LogDatei"
Write-Host ""
Pause
|
und eine kleine .cmd, das ist die datei die man dann einfach anklickt. selbes Muster (neue .txt, einfügen des codes, umbenenn in meinetwegen "PDF-sortieren-neutral.cmd")
Zitat:
@echo off
powershell.exe -NoProfile -ExecutionPolicy Bypass -File "%~dp0PDF-sortieren-neutral.ps1"
|