ext4 / cifs case insensitive mit rsync / cp

djrick

Registered User
Hallo,

Ich habe auf meinem entfernten Server folgende Struktur:

/KUNDE1/backup
/kunde1/daten
/KUNDE2/Backup
/Kunde2/DATEN

und auf meinem lokalen Server habe ich:

/Kunde1/Backup
/KUNDE1/daten
/Kunde2/backup
/Kunde3/daten

Nun möchte ich per Rsync die neusten Daten in meine lokale Kopie kopieren. Dabei dient der erste Teil des Namens immer um den Kunden zu identifizieren. Das Root Verzeichnis ist als Windows Share verfügbar, so dass die Mitarbeiter damit arbeiten können.

Das Problem ist nun:
Linux ist case sensitive, windows case insensive. Nach meinem Sync hab ich /KUNDE1 und /Kunde1. Von Windows aus wird allerdings nur ein Verzeichnis gesehen. Gibt es eine Möglichkeit die Dateien (Verzeichnisse) case insensitive zu kopieren?

Ich habe es schon mit einem Workarround probiert:
Das Verzeichnis auf dem Linuxverzeichnis via mount.cifs auch noch mal lokal zu mounten, in der Hoffnung dass dies dann case insensitive ist, allerdings haben diese Optionen nicht geholfen:

Code:
nocase sec=ntlmv2 nounix

Hat noch jemand eine Idee?
 
Last edited by a moderator:

danton

Debian User
Das kann nicht funktionieren, denn unter Linux sind kunde1 und KUNDE1 zwei unterschiedliche Verzeichnisse, während sie unter Windows das gleiche Verzeichnis meinen.
Die sauberste Lösung ist, einmal die Schreibweisen auf dem Server zu bereinigen, so dass die Verzeichnisnamen (und ggfl. auch Dateinamen) sind in mehr als nur der Groß- und Kleinschreibung unterscheiden. Ich nutze z.B. bei meinen Webseiten für die Verzeichnisse und Dateien grundsätzlich Kleinschreibung.
 

p-st

Member
Als Workaround für bestehende Kunden könnte man sich ein Skript basteln, dass auf dem lokalen Server zunächst Verzeichnisse für alle Kunden anlegt und zusätzlich für jeden Kunden einen Symlink in der alternativen Schreibweise generiert:
Code:
drwxr-xr-x 2 root root 6 Aug 26 18:17 kunde1
lrwxrwxrwx 1 root root 6 Aug 26 18:18 KUNDE1 -> kunde1
...

Dann rsync mit der Option "--keep-dirlinks" aufrufen. Besser wäre es natürlich, das Problem zu lösen.
 

danton

Debian User
Wenn ich das richtig verstanden habe, ist nicht das Syncen auf den lokalen Server das Problem, sondern hinterher das Bereitstellen als Windows-Share, wo bei der vermeintlichen Namesgleichheit für die Windows-Clients Nicht alle Verzeichnisse ansprechbar sind.
 
Last edited by a moderator:

p-st

Member
Mit der Symlink-Methode wären alle Daten in jeweils nur einem Kundenverzeichnis, d.h. über einen Windows-Share sollten dann imho auch alle Unterverzeichnisse angezeigt werden. Und da wie ich jetzt gesehen habe die Unterverzeichnisse auch unterschiedliche Schreibweisen haben (z.B. "Backup" und "backup"), müsste man dort auch entsprechende Symlinks generieren.
 

djrick

Registered User
Falls es mal jemand braucht, ich löse das Problem jetzt mit einem kleinen Script:

1.) Per Rsync in ein Temp-Verzeichnis
2.) Per "find" mit caseinsensitiv die Verzeichnisse rekursiv ermitteln, merken und wenn eine Datei gefunden wird, entsprechend kopieren


Code:
#!/bin/bash
clear
recurse() {
 for i in "$1"/*;do
    if [ -d "$i" ];then
        bname=`basename $i`
        ergcount=`findutils-find $2 -maxdepth 1  -type d -iname "$bname" | wc -l`
        if [ $ergcount -eq 0 ]; then
                erg=`findutils-find $2 -maxdepth 1  -type d -iname "$bname"`
                echo "Lege neues Verzeichnis an: $erg"
                mkdir $erg
        fi

        erg=`findutils-find $2 -maxdepth 1  -type d -iname "$bname"`
        recurse "$i" "$erg"
    elif [ -f "$i" ]; then
        echo "Kopiere Datei nach: $2"
        cp -v "$i" "$2"
    fi
 done
}

recurse /share/TEMP /share/Kunden

Es ist nicht schön, aber selten ;)

Da das ganze auf einem Qnap NAS läuft, verwende ich hier "findutils-find", was dem "normalen" 'find' entspricht.
 

p-st

Member
Vielen Dank!

Ich hab Dein Skript eben mal auf einem Linux-System getestet. Ich musste den inneren if-Block anpassen, ansonsten werden bei mir keine Verzeichnisse im Ziel angelegt:

Code:
#!/bin/bash
recurse() {
 for i in "$1"/*;do
    if [ -d "$i" ];then
        bname=`basename $i`
        ergcount=`find $2 -maxdepth 1  -type d -iname "$bname" | wc -l`
        if [ $ergcount -eq 0 ]; then
                echo "Lege neues Verzeichnis an: $2/$bname"
                mkdir $2/$bname
        fi

        erg=`find $2 -maxdepth 1  -type d -iname "$bname"`
        recurse "$i" "$erg"
    elif [ -f "$i" ]; then
        echo "Kopiere Datei nach: $2"
        cp -v "$i" "$2"
    fi
 done
}

recurse /tmp/TEMP /tmp/Kunden

Zum Test verwende ich folgende Daten
Code:
tmp/TEMP/
tmp/TEMP/kunde1
tmp/TEMP/kunde1/backup
tmp/TEMP/kunde1/backup/test
tmp/TEMP/kunde1/Backup
tmp/TEMP/kunde1/Backup/test2
tmp/TEMP/Kunde1
tmp/TEMP/Kunde1/baCkup
tmp/TEMP/Kunde1/baCkup/test3

Nach Ausführen des Skripts erhalte ich folgendes
Code:
tmp/Kunden/
tmp/Kunden/kunde1
tmp/Kunden/kunde1/backup
tmp/Kunden/kunde1/backup/test3
tmp/Kunden/kunde1/backup/test
tmp/Kunden/kunde1/backup/test2
 

nexus

Well-Known Member
Ich verstehe nicht ganz, warum ihr euch diese Script-Frickelei überhaupt antut :confused:
Einmal die Namensgebung der Verzeichnisse bereinigen und gut isses.

Zumal es bei eurer Scriptlösung sowieso knallen dürfte, wenn zb.

/Kunde/testfile

und

/kunde/testfile

vorhanden sind (Namensgleichheit der Files in unterschiedlichen Verzeichnissen).
 

p-st

Member
Ich verstehe nicht ganz, warum ihr euch diese Script-Frickelei überhaupt antut. Einmal die Namensgebung der Verzeichnisse bereinigen und gut isses.
Du meinst doch nicht etwa händisch, oder? Außerdem schüttelt man sich Skripte, die Rekursion verwenden nicht mal so aus dem Ärmel. Da ist es nützlich wenn man bereits ein funktionierendes Skript hat, auf das man aufbauen kann.

Hier nun eine angepasste Version, die das Überschreiben von Dateien verhindert und alle nicht kopierten Dateien am Ende auflistet, so dass man diese Spezialfälle im Nachgang abarbeiten kann. Weiterhin werden nun auch Leerzeichen in Verzeichnissen/Dateinamen unterstützt. Das Skript löscht zu Beginn das Zielverzeichnis.

Code:
#!/bin/bash
TMPFILE=/tmp/files_not_copied.log
recurse() {
 for i in "$1"/*;do
    if [ -d "$i" ];then
        bname=`basename "$i"`
        ergcount=`find "$2" -maxdepth 1 -type d -iname "$bname" | wc -l`
        if [ $ergcount -eq 0 ]; then
#            echo "Lege neues Verzeichnis an: $2/$bname"
            mkdir "$2/$bname"
        fi
        erg=`find "$2" -maxdepth 1 -type d -iname "$bname"`
        recurse "$i" "$erg"
    elif [ -f "$i" ]; then
        bname=`basename "$i"`
        filecount=`find "$2" -maxdepth 1 -type f -iname "$bname" | wc -l`
        if [ $filecount -eq 0 ]; then
#            echo "Kopiere Datei nach: $2"
            cp -v "$i" "$2"
        else
            echo "$i" >> $TMPFILE
        fi
    fi
 done
}

rm -rf /tmp/Kunden/*
rm $TMPFILE
recurse /tmp/TEMP /tmp/Kunden
if [ -f $TMPFILE ]; then
    echo "=============================================="
    echo "WARNUNG: Folgende Dateien wurden nicht kopiert"
    cat $TMPFILE
    exit 1
fi

Mit folgenden Daten

Code:
/tmp/TEMP/
/tmp/TEMP/Kunde1
/tmp/TEMP/Kunde1/testdatei
/tmp/TEMP/Kunde1/testdatei2
/tmp/TEMP/kunde1
/tmp/TEMP/kunde1/testdatei
/tmp/TEMP/kunde1/Testdatei
/tmp/TEMP/kunde2
/tmp/TEMP/kunde2/BACKUP
/tmp/TEMP/kunde2/BACKUP/testdatei
/tmp/TEMP/Kunde2
/tmp/TEMP/Kunde2/Backup
/tmp/TEMP/Kunde2/Backup/testdatei2

generiert das Skript nun folgende, Windows-Share kompatible Struktur

Code:
‘/tmp/TEMP/kunde1/testdatei’ -> ‘/tmp/Kunden/kunde1/testdatei’
‘/tmp/TEMP/Kunde1/testdatei2’ -> ‘/tmp/Kunden/kunde1/testdatei2’
‘/tmp/TEMP/kunde2/BACKUP/testdatei’ -> ‘/tmp/Kunden/kunde2/BACKUP/testdatei’
‘/tmp/TEMP/Kunde2/Backup/testdatei2’ -> ‘/tmp/Kunden/kunde2/BACKUP/testdatei2’
==============================================
WARNUNG: Folgende Dateien wurden nicht kopiert
/tmp/TEMP/kunde1/Testdatei
/tmp/TEMP/Kunde1/testdatei

Voila!
 

nexus

Well-Known Member
Das mag schon mal ein funktionierender Workaround sein. Aber ohne den Kontext der betroffenen Dateien zu kennen, ist eine Aussage über die Nützlichkeit dieser Lösung eher schwierig, denn

Das Root Verzeichnis ist als Windows Share verfügbar, so dass die Mitarbeiter damit arbeiten können.

an dieser Stelle muß man den Mitarbeitern erstmal begreiflich machen, warum sich einige Dateinamen geändert haben und

Hier nun eine angepasste Version, die das Überschreiben von Dateien verhindert und alle nicht kopierten Dateien am Ende auflistet, so dass man diese Spezialfälle im Nachgang abarbeiten kann.

hier wird es spätestens dann vom Aufwand für die nötige händische Nacharbeit problematisch, wenn nicht nur 2 oder 3 sondern 200 oder 300 Kundenverzeichnisse existieren und dementsprechend viele Dateien umbenannt bzw. garnicht kopiert wurden.

Aber das kann und muß der TE für sich entscheiden ;)
 
Last edited by a moderator:

djrick

Registered User
Aber das kann und muß der TE für sich entscheiden ;)
Richtig :)

Auf das "richtige" Namensvergabe habe ich leider keinen Einfluss. Ich kann nicht vorher sagen ob das Verzeichnis groß oder klein geschrieben wird. Ich kann nur den Namen selbst vorhersagen.

Das löschen des Temp Verzeichnisses wird an anderer Stelle bereits gemacht und habe ich deshalb an dieser Stelle nicht behandelt.
 
Top