The estimated reading time 14 minutes
Den heutigen Post möchte ich einer Legende des deutschen Fernsehens widmen. „Die Maus“ wird dieses Jahr 50 und hat mich bereits durch die Kindheit begleitet, so wie sie es heute bei meiner Tochter tut. Dieses Stück Fernsehgeschichte soll auch auf meinem Blog den ihr gebührenden Platz haben, deshalb habe ich diese Post ausgewählt. Die Sendung vermittelt Wissen spielerisch und auch Erwachsene können immer wieder etwas lernen. Ganz im Sinne meines Blogs.
Also liebe Maus und natürlich alle Charaktere der Sendung:
Herzlichen Glückwunsch zum 50. Geburtstag
Zurück zu den Umlauten:
Für andere Länder sind unsere deutschen Umlaute ungewöhnlich und eigentlich kann keiner so richtig damit umgehen.
Auf Grund meines Namens bin ich in diverse Probleme geraten, da es nach wie vor einige Systeme gibt, die mit Umlauten der deutschen Sprache Probleme haben. Das hat mich veranlasst ein kleines PowerShell Skript zu schreiben, welches diese in Ordnernamen und Dateien findet und auf Wunsch auch eliminieren kann. Anlass war mein Synology NAS, welches zwar Umlaute unterstützt, nicht aber in Kombination mit dem Hochladen von Dateien in OneDrive Business. Siehe Synology Forum
Machen wirs kurz, wie sieht das Ganze aus?
Aufruf nur prüfen: c:\temp\umlautfinder.ps1 -checkpath [PfadZumOrdner] -logpath [PfadZumLogOrdner] -whatif
Aufruf zum Ändern: c:\temp\umlautfinder.ps1 -checkpath [PfadZumOrdner] -logpath [PfadZumLogOrdner] -changeumlauts
<# #### requires ps-version 3.0 #### <# .SYNOPSIS searches for umlauts in folder and filenames only for logging or either changing them. Replacement of these characters Replace('ä','ae').Replace('Ä','Ae').Replace('ö','oe').Replace('Ö','Oe').Replace('ü','ue').Replace('Ü','Ue').Replace('ß','ss') .DESCRIPTION script searches for special characters in files and folders ('ä','ö','ü','Ä','Ö','Ü','ß') .PARAMETER checkpath path where to search for special characters .PARAMETER logpath path for logfiles .PARAMETER whatif creates protocoll but no changes (if no switch parameter definied, whatif is used) .PARAMETER changeumlauts creates protocoll and changes umlauts .INPUTS - .OUTPUTS two logfiles will be created (files and folders) .NOTES Version: 0.1 Author: Alexander Koehler Creation Date: Wednesday, March 31st 2021, 10:07:13 pm File: umlautfinder.ps1 Copyright (c) 2021 blog.it-koehler.com HISTORY: Date By Comments ---------- --- ---------------------------------------------------------- .LINK https://blog.it-koehler.com/en/ .COMPONENT Required Modules: .LICENSE Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the Software), to deal in the Software without restriction, including without limitation the rights to use copy, modify, merge, publish, distribute sublicense and /or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED AS IS, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. .EXAMPLE .\umlautfinder.ps1 -checkpath \\server\share -logpath C:\temp\ -whatif C:\folder | .\umlautfinder.ps1 -logpath C:\temp\ .\umlautfinder.ps1 -checkpath X:\ -logpath C:\log\ -changeumlauts .\umlautfinder.ps1 -checkpath X:\,\\server\share2,C:\documents -logpath C:\log\ -changeumlauts # #> [CmdletBinding()] param ( [Parameter(Mandatory = $true, HelpMessage='"w:\","x:\"',ValueFromPipeline,ValueFromPipelineByPropertyName)] #test if the folder exists, otherwise throw an error.Test if the user provides a full path to the folder [Object[]] [ValidateScript({ #check if destination is a folder foreach($obj in $_){ if(($_ | Test-Path -PathType Leaf)){ throw "The path argument has to be a folder. File paths are not allowed." } else{ return $true } } })] #check if it is a path to folder #[System.IO.DirectoryInfo]$checkpath, $checkpath, #test if the file exists, otherwise throw an error.Test if the user provides a full path to the file [Parameter(Mandatory = $true , HelpMessage="c:\logs\")] [ValidateScript({ if(($_ | Test-path -PathType Leaf)){ throw "path has to be a folder, no files allowed!" } return $true })] #check if it is a folder path [System.IO.DirectoryInfo]$logpath, #parameter for executing and changing special characters (with logging) [Parameter(Mandatory = $false)] [switch]$changeumlauts, #whatif parameter (only logging) [Parameter(Mandatory = $false)] [switch]$whatif=$false ) #file logging [string] $csvLogfilePath = "$logpath" [string] $csvLogfileDate = Get-Date -Format "yyyy-MM-dd-HH-mm-ss" [string] $csvLogfileNamePrefix = "umlaut-finder-files-" [string] $csvLogfileName = $("$csvLogfileNamePrefix" + "$csvLogfileDate" + ".csv") [string] $csvLogfile = $csvLogfilePath + "\" + $csvLogfileName #folder logging [string] $csvLogfilePathfolder = "$logpath" [string] $csvLogfileNamePrefixfolder = "umlaut-finder-folder-" [string] $csvLogfileName = $("$csvLogfileNamePrefixfolder" + "$csvLogfileDate" + ".csv") [string] $csvLogfilefolder = $csvLogfilePathfolder + "\" + $csvLogfileName #adding tableheader Add-Content -Path "$csvLogfile" -Value "#### files with special characters" -Encoding UTF8 Add-Content -Path "$csvLogfile" -Value "folderpath;filename;duplicates;maxpathlengtherror" -Encoding UTF8 Add-Content -Path "$csvLogfilefolder" -Value "#### Folders with special characters" -Encoding UTF8 Add-Content -Path "$csvLogfilefolder" -Value "folderpath;duplicates;maxpathlengtherror" -Encoding UTF8 foreach($pathstocheck in $checkpath){ #search patterns $pattern = 'ä','ö','ü','Ä','Ö','Ü','ß' foreach($folder in $pathstocheck){ Write-Host "####Searching files with special characters in folder: $folder ..." -ForegroundColor Magenta #find all files/folders inside specified path $files=Get-ChildItem -Path "$Folder" -Recurse -File | Sort-Object fullname $folders = Get-ChildItem -Path "$Folder" -Recurse -Directory | Sort-Object fullname ####searching for files foreach ($file in $files) { #check pathlength $fullpathlength = ($file).Fullname.Length #filename without file extension $umlautfile = $file.BaseName $umlauts = $(try {Select-String -InputObject $umlautfile -Pattern $pattern -AllMatches} catch {$null}) #only rename files with umlauts If ($umlauts -ne $Null) { $filename1 = ($file).Name $path1 = ($file).DirectoryName Write-Host "files with special characters: $filename1 in folder: $path1" -ForegroundColor Yellow #rename files with less than 260 pathlength if($fullpathlength -lt 260){ Add-Content -Path $csvLogfile -Value "$path1;$filename1" -Encoding UTF8 #check if parameter whatif present if(($whatif.IsPresent) -or ($whatif -eq $false)){ #creating new name (replacement) $NewName=$file.BaseName.Replace('ä','ae').Replace('Ä','Ae').Replace('ö','oe').Replace('Ö','Oe').Replace('ü','ue').Replace('Ü','Ue').Replace('ß','ss')+$file.Extension #checks if exists already if(Test-Path "$path1\$NewName"){ #creating new name with extension --1 $NewName=$file.BaseName.Replace('ä','ae').Replace('Ä','Ae').Replace('ö','oe').Replace('Ö','Oe').Replace('ü','ue').Replace('Ü','Ue').Replace('ß','ss')+"--1"+$file.Extension Write-Host "duplicated file name detected new name $NewName" -ForegroundColor Red Add-Content -Path "$csvLogfile" -Value "$path1;$filename1;DUP--$NewName" -Encoding UTF8 $file | Rename-Item -NewName $NewName -WhatIf } else{ $file | Rename-Item -NewName $NewName -WhatIf } } #do renaming if present if($changeumlauts.IsPresent){ $NewName=$file.BaseName.Replace('ä','ae').Replace('Ä','Ae').Replace('ö','oe').Replace('Ö','Oe').Replace('ü','ue').Replace('Ü','Ue').Replace('ß','ss')+$file.Extension #checks if already exists if(Test-Path "$path1\$NewName"){ Write-Host "duplicated file with name $newname detected, adding --1" -ForegroundColor Red $NewName=$file.BaseName.Replace('ä','ae').Replace('Ä','Ae').Replace('ö','oe').Replace('Ö','Oe').Replace('ü','ue').Replace('Ü','Ue').Replace('ß','ss')+"--1"+$file.Extension $file | Rename-Item -NewName "$NewName" Add-Content -Path "$csvLogfile" -Value "$path1;$filename1;DUP--$NewName" -Encoding UTF8 } else{$file | Rename-Item -NewName $NewName} } } #if path is more than 260 chars else{ if(($whatif.IsPresent) -or ($whatif -eq $false)){ $fullfilepath = ($file).fullname Write-Host "WARNING Special character found but path $fullfilepath more than 260 characterslong,length: $fullpathlength" -ForegroundColor Yellow #change path with .net function for long paths $pathtofile = ($file).Fullname $pathtoolong = "\\?\$pathtofile" $NewName=$file.BaseName.Replace('ä','ae').Replace('Ä','Ae').Replace('ö','oe').Replace('Ö','Oe').Replace('ü','ue').Replace('Ü','Ue').Replace('ß','ss')+$file.Extension #rename Rename-Item -LiteralPath "$pathtoolong" -NewName $NewName -WhatIf Add-Content -Path $csvLogfile -Value "$path1;$filename1;;WARNING MAX-Path-Length $fullpathlength (Rename done)" -Encoding UTF8 } if($changeumlauts.IsPresent){ $fullfilepath = ($file).fullname Write-Host "WARNING Special character found but path $fullfilepath more than 260 characterslong,length: $fullpathlength" -ForegroundColor Yellow #change path with .net function for long paths $pathtofile = ($file).Fullname $pathtoolong = "\\?\$pathtofile" $NewName=$file.BaseName.Replace('ä','ae').Replace('Ä','Ae').Replace('ö','oe').Replace('Ö','Oe').Replace('ü','ue').Replace('Ü','Ue').Replace('ß','ss')+$file.Extension #rename file Rename-Item -LiteralPath "$pathtoolong" -NewName $NewName Add-Content -Path $csvLogfile -Value "$path1;$filename1;;WARNING MAX-Path-Length $fullpathlength (Rename done)" -Encoding UTF8 } } } else{ $dateiohneumlaute = ($file).Name Write-Host "File: $dateiohneumlaute has no special characters" -ForegroundColor Green } } Write-Host "#### Searching for folders with special characters..." -ForegroundColor Magenta ##searching foldername foreach ($fold in $folders) { #checking folder length $fullpathlength = ($fold).Fullname.Length #getting foldername $umlautfolder = $fold.BaseName #check if folder contains special character $umlautfold = $(try {Select-String -InputObject $umlautfolder -Pattern $pattern -AllMatches} catch {$null}) If ($umlautfold -ne $Null) { $ordnername = ($fold).Name #get full path $ordnerpfad = ($fold).FullName Write-Host "Folder with special character found: $ordnername see path: $ordnerpfad" -ForegroundColor Yellow #check if folderpath is longer than 260 chars if($fullpathlength -lt 260){ Add-Content -Path "$csvLogfilefolder" -Value "$ordnerpfad" -Encoding UTF8 #parameter whatif is set, no changes made to folder structure (simulation) if(($whatif.IsPresent) -or ($whatif -eq $false)){ $NewName=$fold.Name.Replace('ä','ae').Replace('Ä','Ae').Replace('ö','oe').Replace('Ö','Oe').Replace('ü','ue').Replace('Ü','Ue').Replace('ß','ss') $newpath = (($fold | Select-Object PSparentpath -ExpandProperty PSparentpath) + "\$NewName") #check if the folder already exists if(Test-Path "$newpath"){ Write-Host "duplicated folders detected, adding --1" -ForegroundColor Red $NewName=$fold.BaseName.Replace('ä','ae').Replace('Ä','Ae').Replace('ö','oe').Replace('Ö','Oe').Replace('ü','ue').Replace('Ü','Ue').Replace('ß','ss') $Newname = "$NewName--1" $fold | Rename-Item -NewName "$NewName" -WhatIf #additional logging Add-Content -Path "$csvLogfilefolder" -Value "$ordnerpfad;DUP--$NewName (Rename done)" -Encoding UTF8 } else{ $fold | Rename-Item -NewName $NewName -WhatIf } } #if parameter is set if($changeumlauts.IsPresent){ $NewName=$fold.Name.Replace('ä','ae').Replace('Ä','Ae').Replace('ö','oe').Replace('Ö','Oe').Replace('ü','ue').Replace('Ü','Ue').Replace('ß','ss') $newpath = (($fold | Select-Object PSparentpath -ExpandProperty PSparentpath) + "\$NewName") #check if the new folder name already exists if(Test-Path "$newpath"){ Write-Host "duplicated folders detected, adding --1" -ForegroundColor Red $NewName=$fold.BaseName.Replace('ä','ae').Replace('Ä','Ae').Replace('ö','oe').Replace('Ö','Oe').Replace('ü','ue').Replace('Ü','Ue').Replace('ß','ss') $Newname = "$NewName--1" $fold | Rename-Item -NewName "$NewName" #additional logging Add-Content -Path "$csvLogfilefolder" -Value "$ordnerpfad;DUP--$NewName (Rename done)" -Encoding UTF8 } else{$fold | Rename-Item -NewName $NewName} } } #if path is longer than 260 chars else{ #whatif or nothing defined if(($whatif.IsPresent) -or ($whatif -eq $false)){ Write-Host "WARNING Special character found but path $ordnerpfad more than 260 characterslong,length: $fullpathlength" -ForegroundColor Yellow #change path with .net function for long paths $pathtoolong = "\\?\$ordnerpfad" $NewName=$fold.BaseName.Replace('ä','ae').Replace('Ä','Ae').Replace('ö','oe').Replace('Ö','Oe').Replace('ü','ue').Replace('Ü','Ue').Replace('ß','ss')+$file.Extension #rename $pathtoolong | Rename-Item -NewName "$NewName" -WhatIf Add-Content -Path $csvLogfile -Value "$ordnerpfad;WARNING MAX-Path-Length $fullpathlength (Rename done)" -Encoding UTF8 } if($changeumlauts.IsPresent){ Write-Host "WARNING Special character found but path $ordnerpfad more than 260 characterslong,length: $fullpathlength" -ForegroundColor Yellow #change path with .net function for long paths $pathtoolong = "\\?\$ordnerpfad" $NewName=$fold.BaseName.Replace('ä','ae').Replace('Ä','Ae').Replace('ö','oe').Replace('Ö','Oe').Replace('ü','ue').Replace('Ü','Ue').Replace('ß','ss')+$file.Extension #rename $pathtoolong | Rename-Item -NewName "$NewName" Add-Content -Path $csvLogfile -Value "$ordnerpfad;WARNING MAX-Path-Length $fullpathlength (Rename done)" -Encoding UTF8 } } } else{ $ordnerohneumlaute = ($fold).Name Write-Host "folder: $ordnerohneumlaute not containing special characters." -ForegroundColor Green } } } }
Was das Skript kann:
- Skript kann Umlaute in lokalen Ordnern/Dateien und Netzwerkfreigaben finden
- es kann Umlaute in Ordnern und Dateien nach festen Definitionen ändern (Bsp: Ä=Ae,ö=oe,ß=ss), falls der Parameter gesetzt ist
- außerdem Umlauten suchen und eine Protokoll CSV ausgeben (ohne Änderungen vorzunehmen)
- sollte es bereits eine Datei /Ordner mit dem selben Namen geben, wird „–1“ an den Namen angehängt (wird im Log bei der Spalte Duplicate angezeigt)
- es kann mehrere Pfade nacheinander durchsuchen (muss im Pfad angegeben werden)
- es erkennt wenn kein Pfad angegeben wird
- Dateien und Ordner werden in separate CSV Dateien geloggt
- Dateien und Ordner mit langem Pfad (mehr als 260 Zeichen) werden ebenfalls umbenannt
- Ordnerpfade können per Pipeline übergeben werden ( „C:\ordner“ | .\umlautfinder.ps1 -logpath c:\log -whatif)
Was es nicht kann:
- funktioniert nicht auf älteren Systemen (PowerShell 3.0 wird benötigt)
- kann den Namen der Logdatei nicht angegeben werden
- es werden immer Ordner UND Dateien geändert (keine Auswahl möglich)
- keine erweiterte Fehlerbehandlung (nur zu lange Pfade über 260 Zeichen)
Gerne bin ich für Verbesserungsvorschläge / Featurerequests offen. Lasst mir einfach einen Kommentar da oder schreibe mich direkt an. Wenn euch das Skript weitergebracht hat, lasst es mich ebenfalls wissen mit dem Button „Helpful“. Vielen Dank und weiterhin viel Erfolg.
an sich ein super Script, nur leider bei mir ohne Funktion:
„File: Äste.txt has no special characters“
Das Problem wurde gelöst. Hier handelte es sich um ein Kodierungsproblem. Die Sonderzeichen wurden beim Kopieren des Skriptes nicht richtig übertragen.
Vielen Dank fürs Feedback.
Viele Grüße
A. Köhler
Hallo,
leider bei mir immer noch…
folder: Bäderhalle not containing special characters.
Dennoch Danke für die Mühe!!
Hallo Marius,
schon mal versucht die PS1 Datei aus github herunterzuladen? Hier der Link:
Viele Grüße
Alexander
funktioniert nun! Merci