diff --git a/rename_special_chars.sh b/rename_special_chars.sh new file mode 100644 index 0000000..bb20026 --- /dev/null +++ b/rename_special_chars.sh @@ -0,0 +1,199 @@ +#!/usr/bin/env bash + +################################################################################ +# +# Rename Special Characters to Underscores +# +# Skript zum Ersetzen von Sonderzeichen (|, <, >) durch Unterstriche (_) +# in Datei- und Ordnernamen unter macOS und Linux +# +# Dieses Skript durchsucht rekursiv einen angegebenen Ordner und benennt +# alle Dateien und Unterordner um, die problematische Sonderzeichen enthalten. +# Dabei werden mehrfache Unterstriche und ungewollte Leerzeichen vermieden. +# +# Kompatibilität: macOS und Linux +# +# Copyright (c) 2025 Dominik Höfling +# +# Dieses Programm ist freie Software. Sie können es unter den Bedingungen +# der GNU General Public License, wie von der Free Software Foundation +# veröffentlicht, weitergeben und/oder modifizieren, entweder gemäß +# Version 3 der Lizenz oder (nach Ihrer Option) jeder späteren Version. +# +# Die Veröffentlichung dieses Programms erfolgt in der Hoffnung, dass es +# Ihnen von Nutzen sein wird, aber OHNE IRGENDEINE GARANTIE, sogar ohne +# die implizite Garantie der MARKTREIFE oder der VERWENDBARKEIT FÜR EINEN +# BESTIMMTEN ZWECK. Details finden Sie in der GNU General Public License. +# +# Sie sollten ein Exemplar der GNU General Public License zusammen mit +# diesem Programm erhalten haben. Falls nicht, siehe +# . +# +################################################################################ + +# Farben für bessere Lesbarkeit +RED='\033[0;31m' +GREEN='\033[0;32m' +YELLOW='\033[1;33m' +NC='\033[0m' # No Color + +# Standardwerte +DRY_RUN=false +TARGET_DIR="" + +# Hilfefunktion +show_help() { + echo "Verwendung: $0 [OPTIONEN] ZIELORDNER" + echo "" + echo "Ersetzt Sonderzeichen (|, <, >) durch Unterstriche (_) in allen" + echo "Datei- und Ordnernamen." + echo "" + echo "Optionen:" + echo " -d, --dry-run Testlauf ohne tatsächliche Umbenennung" + echo " -h, --help Diese Hilfe anzeigen" + echo "" + echo "Kompatibilität: macOS und Linux" + echo "" + echo "Beispiel:" + echo " $0 -d ~/Dokumente/MeinOrdner # Testlauf" + echo " $0 ~/Dokumente/MeinOrdner # Tatsächliche Umbenennung" +} + +# Funktion zum Bereinigen des Dateinamens +clean_name() { + local name="$1" + + # 1. Ersetze alle Varianten von Sonderzeichen mit Leerzeichen + # Behandelt: "|", " |", "| ", " | ", "<", ">", " <", "> ", etc. + name=$(echo "$name" | sed -E 's/ *[|<>] */ /g') + + # 2. Ersetze verbleibende Sonderzeichen durch Leerzeichen + name=$(echo "$name" | tr '|<>' ' ') + + # 3. Ersetze mehrfache Leerzeichen durch einzelnes Leerzeichen + name=$(echo "$name" | sed -E 's/ +/ /g') + + # 4. Entferne Leerzeichen am Anfang und Ende + name=$(echo "$name" | sed -E 's/^ +//; s/ +$//') + + # 5. Ersetze Leerzeichen durch Unterstrich + name=$(echo "$name" | tr ' ' '_') + + # 6. Ersetze mehrfache Unterstriche durch einzelnen Unterstrich + name=$(echo "$name" | sed -E 's/_+/_/g') + + # 7. Entferne Unterstriche am Anfang und Ende + name=$(echo "$name" | sed -E 's/^_+//; s/_+$//') + + echo "$name" +} + +# Funktion zum Umbenennen +rename_item() { + local path="$1" + local dir=$(dirname "$path") + local old_name=$(basename "$path") + local new_name=$(clean_name "$old_name") + + # Nur umbenennen, wenn sich der Name geändert hat + if [ "$old_name" != "$new_name" ]; then + local new_path="$dir/$new_name" + + if [ "$DRY_RUN" = true ]; then + echo -e "${YELLOW}[TEST]${NC} $old_name → $new_name" + else + # Prüfe, ob Ziel bereits existiert + if [ -e "$new_path" ]; then + echo -e "${RED}[FEHLER]${NC} Ziel existiert bereits: $new_name" + return 1 + fi + + # Führe Umbenennung durch + if mv "$path" "$new_path"; then + echo -e "${GREEN}[OK]${NC} $old_name → $new_name" + else + echo -e "${RED}[FEHLER]${NC} Konnte nicht umbenennen: $old_name" + return 1 + fi + fi + fi +} + +# Parameter verarbeiten +while [[ $# -gt 0 ]]; do + case $1 in + -d|--dry-run) + DRY_RUN=true + shift + ;; + -h|--help) + show_help + exit 0 + ;; + *) + TARGET_DIR="$1" + shift + ;; + esac +done + +# Prüfe, ob Zielordner angegeben wurde +if [ -z "$TARGET_DIR" ]; then + echo -e "${RED}Fehler: Kein Zielordner angegeben.${NC}" + echo "" + show_help + exit 1 +fi + +# Prüfe, ob Zielordner existiert +if [ ! -d "$TARGET_DIR" ]; then + echo -e "${RED}Fehler: Ordner existiert nicht: $TARGET_DIR${NC}" + exit 1 +fi + +# Zeige Modus an +if [ "$DRY_RUN" = true ]; then + echo -e "${YELLOW}=== TESTMODUS - Keine tatsächlichen Änderungen ===${NC}" +else + echo -e "${GREEN}=== PRODUKTIVMODUS - Dateien werden umbenannt ===${NC}" + echo -e "${YELLOW}Warnung: Erstellen Sie vorher ein Backup!${NC}" + read -p "Fortfahren? (j/N) " -n 1 -r + echo + if [[ ! $REPLY =~ ^[Jj]$ ]]; then + echo "Abgebrochen." + exit 0 + fi +fi + +echo "" +echo "Durchsuche: $TARGET_DIR" +echo "" + +# Zähler +count_renamed=0 +count_errors=0 + +# Verwende find mit depth-first (tiefste Ebene zuerst) +# Dies verhindert Probleme beim Umbenennen von Elternordnern +while IFS= read -r -d '' item; do + if rename_item "$item"; then + ((count_renamed++)) + else + ((count_errors++)) + fi +done < <(find "$TARGET_DIR" -depth -print0 | grep -zE '[|<>]') + +# Zusammenfassung +echo "" +echo "=== Zusammenfassung ===" +if [ "$DRY_RUN" = true ]; then + echo "Würde $count_renamed Elemente umbenennen" +else + echo "Umbenannte Elemente: $count_renamed" +fi +echo "Fehler: $count_errors" +echo "" + +if [ "$DRY_RUN" = true ]; then + echo -e "${YELLOW}Führen Sie das Skript ohne -d aus, um tatsächlich umzubenennen.${NC}" +fi