Dateipfad einer einzigen Datei ermitteln (os.walk?)

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
Antworten
Benutzeravatar
NoPy
User
Beiträge: 158
Registriert: Samstag 28. Dezember 2013, 12:39

Hi,

ich muss in einer DB den Dateinamen hinsichtlich Groß- Klein- Schreibung korrigieren.
Gibt es da schon was oder muss man os.walk vergewaltigen? Ich will die Datei nicht öffnen müssen, das kostet zu viel Zeit.

eigentlich benötige ich eine Funktion a la

Code: Alles auswählen

def KorrekterDateiname(AlterDateiName):
    return NeuerDateiName
    
a = 'C:\\irgendwie\\GESCHRIEBEN\\DaTeInAmE.tXt'
b = KorrekterDateiname(a)
print (b)
'C:\\Irgendwie\\Geschrieben\\DateiName.TXT'
Hat jemand eine Idee?
Benutzeravatar
pillmuncher
User
Beiträge: 1530
Registriert: Samstag 21. März 2009, 22:59
Wohnort: Pfaffenwinkel

Was wäre denn in dem Kontext die korrekte Schreibweise für zB. "expertsexchange"?
In specifications, Murphy's Law supersedes Ohm's.
Benutzeravatar
NoPy
User
Beiträge: 158
Registriert: Samstag 28. Dezember 2013, 12:39

Das weiß eben nur das Dateiverzeichnis :(

also wenn auf dem Datenträger die Datei zu finden ist unter

D:\Hallo\Welt\IrgendeineDatei.TXT

dann soll ein Funktionsaufruf F(d:\hallo\WELT\irgendeinedatei.txt) eben das liefern
Benutzeravatar
sparrow
User
Beiträge: 4538
Registriert: Freitag 17. April 2009, 10:28

Ich verstehe das Problem nicht. Seit wann sind Windows-Dateisysteme case-sensitive?
Benutzeravatar
NoPy
User
Beiträge: 158
Registriert: Samstag 28. Dezember 2013, 12:39

Wer spricht von Windows? Du meinst, wegen "C:"
Falls es Dir für das Verständnis hilft:

DIe Dateien liegen auf einem Linux- System (das für mein Windows als "X:" angebunden ist).
Der Dienst, der die Dateien ausliefert, schaut in die eine DB und holt dort den Dateinamen raus. Dort ist aber hinsichtlich der Groß- Klein- Schreibung "Unordnung", da die Daten ursprünglich über einen Windows- Client gelesen wurden. Und damit findet der Dienst die Dateien nicht.

Also muss ich letzlich etwas in der Form (pseudo)

Code: Alles auswählen

SELECT DATEINAME FROM TABELLEXY WHERE ID = 12345;
NeuerDateiname = ErmittleKorrektenDateinamen(DATEINAME) 
UPDATE TABELLEXY SET DATEINAME = NeuerDateiname WHERE ID = 12345
anstellen
Benutzeravatar
__blackjack__
User
Beiträge: 14045
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@NoPy: Man könnte mit `pathlib.Path` und der `glob()`-Methode ein Wörterbuch (`dict`) erstellen das alle Pfade/Dateinamen in Kleinbuchstaben umgewandelt auf den tatsächlichen Pfad/Dateinamen abbildet. Und dann kannst Du die Namen aus der Datenbank in Kleinbuchstaben gewandelt dazu verwenden um den tatsächlichen Namen in dem Wörterbuch nachzuschlagen.
„A life is like a garden. Perfect moments can be had, but not preserved, except in memory. LLAP” — Leonard Nimoy's last tweet.
Benutzeravatar
sparrow
User
Beiträge: 4538
Registriert: Freitag 17. April 2009, 10:28

Witziges Verhalten von glob unter Windows:

Code: Alles auswählen

>>> os.listdir("d:\\test")
['cAmel.TxT']
>>> p = Path("d:\\test")
>>> [e for e in p.glob("*")]
[WindowsPath('d:/test/cAmel.TxT')]
>>> [e for e in p.glob("camel.txt")]
[WindowsPath('d:/test/camel.txt')]
>>> [e for e in p.glob("CAMEL.TXT")]
[WindowsPath('d:/test/camel.txt')]
Benutzeravatar
NoPy
User
Beiträge: 158
Registriert: Samstag 28. Dezember 2013, 12:39

__blackjack__ hat geschrieben: Freitag 26. Juli 2019, 13:06 @NoPy: Man könnte mit `pathlib.Path` und der `glob()`-Methode ein Wörterbuch (`dict`) erstellen das alle Pfade/Dateinamen in Kleinbuchstaben umgewandelt auf den tatsächlichen Pfad/Dateinamen abbildet. Und dann kannst Du die Namen aus der Datenbank in Kleinbuchstaben gewandelt dazu verwenden um den tatsächlichen Namen in dem Wörterbuch nachzuschlagen.
Tatsächlich mach ich das gerade, mit os.walk (als workaround, allerdings ist das Verhalten auch nicht immer so, wie ich es erwarte).

Das Problem: Um den korrekten Pfad weniger Dateien zu ermitteln, muss ich erst das komplette Verzeichnis einlesen, was mehrere Minuten dauert.
Für einen Prozess, der gelegentlich läuft, ist das natürlich akzeptabel, aber um auf die Schnelle für wenige Dateien die Prüfung durchzuführen, ist das schwierig zu vermitteln.
sparrow hat geschrieben: Freitag 26. Juli 2019, 13:42 Witziges Verhalten von glob unter Windows:
Muss ich ausprobieren.

Aber irgendetwas, wie

Code: Alles auswählen

f = AttachFile('c:\\CaMeL.TxT')
print (f.filename)
gibt es anscheinend nicht?
Benutzeravatar
sparrow
User
Beiträge: 4538
Registriert: Freitag 17. April 2009, 10:28

Das sollte dein Problem lösen:

Code: Alles auswählen

from pathlib import Path

def get_casesensitive_path(directory, filename):
    path = Path(directory)
    hits = [e for e in path.glob(filename)]
    if len(hits) == 1:
        return hits[0].resolve()
    # TODO: What if the hit is not exactly 1?


print(get_casesensitive_path("d:\\test", "camel.txt"))
# D:\TEST\cAmel.TxT 
Benutzeravatar
NoPy
User
Beiträge: 158
Registriert: Samstag 28. Dezember 2013, 12:39

sparrow hat geschrieben: Freitag 26. Juli 2019, 14:24 Das sollte dein Problem lösen:

Code: Alles auswählen

from pathlib import Path

def get_casesensitive_path(directory, filename):
    path = Path(directory)
    hits = [e for e in path.glob(filename)]
    if len(hits) == 1:
        return hits[0].resolve()


print(get_casesensitive_path("d:\\test", "camel.txt"))
# D:\TEST\cAmel.TxT 
HA! Witzige Sache :)
Jetzt erhalte ich
\\unsere.url.de\irgendeinVerzeichnis\DasIchNichtKenne\DasBasisVerzeichnisDasIchKenne\UndAllesSchoenGroszKlein\Datei.txt

Damit kann ich auf alle Fälle umgehen, vielen Dank!
Benutzeravatar
sparrow
User
Beiträge: 4538
Registriert: Freitag 17. April 2009, 10:28

Das wäre eine Alternative, bei der man ausnutzt, dass .glob die Großschreibung behält, wenn man den Joker verwendet. Aber dann kann tatsächlich mehr als ein File getroffen werden:

Code: Alles auswählen

from pathlib import Path

def get_casesensitive_path(directory, filename):
    path = Path(directory)
    hits = [e for e in path.glob(f"{filename}*")]
    if len(hits) == 1:
        return hits[0]
    else:
        raise Exception(f"'{filename}' hits not exactly one file: {hits}")


print(get_casesensitive_path("d:\\test", "camel.txt"))
Benutzeravatar
__blackjack__
User
Beiträge: 14045
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@sparrow: Man sollte da vielleicht aus `hits` noch die Ergebnisse rausfiltern die eine andere Länge als `filename` haben, denn wenn man damit nach `test.py` sucht und eine `test.pyc` im gleichen Ordner liegt, dann hat man ganz sicher mehr als einen Treffer, aber der falsche lässt sich leicht an der Länge identifizieren.
„A life is like a garden. Perfect moments can be had, but not preserved, except in memory. LLAP” — Leonard Nimoy's last tweet.
Sirius3
User
Beiträge: 18270
Registriert: Sonntag 21. Oktober 2012, 17:20

@sparrow: LCs, die nichts anders machen, als einen Iterator abzulaufen, kann man einfacher als list()-Aufruf ausdrücken.
Oder eben __blackjacks__ Hinweis folgende:

Code: Alles auswählen

return min(path.glob(f"{filename}*"), key=len))
Oder um nur ein Ergebnis zu bekommen, kann man mit Zeichengruppen arbeiten:

Code: Alles auswählen

return next(path.glob(f"{filename[:-1]}[{filename[-1]}]")))
Benutzeravatar
NoPy
User
Beiträge: 158
Registriert: Samstag 28. Dezember 2013, 12:39

Vielen Dank für Eure Antworten. Glücklicherweise spielen Joker bei mir keine Rolle. Theoretisch könnte jemand "stänkern", aber dann würde im Zweifelsfall einfach keine Korrektur stattfinden. Also insofern: Fertig
Antworten