Verzeichnis/Dateiliste als tex-Datei ausgeben

Du hast eine Idee für ein Projekt?
Melewo
User
Beiträge: 320
Registriert: Mittwoch 3. Mai 2017, 16:30

Donnerstag 29. Juni 2017, 20:38

Nur noch einmal ein Nachtrag, um das Beispiel nicht so stehen zu lassen. Dieses None war kein None, sondern nur ein leerer String, einen Teil der Statements auf elif und die Sortierung geändert.

Code: Alles auswählen

def wandle_datum(data):
    return int(time.mktime(time.strptime(data, "%d.%m.%Y")))

def suche_files(durchlaufe, auswahl, endung, vondate, bisdate):
    os.stat_float_times(False)
    file_dict = {}
    rueckgabe = []

    for verzeichnisse, unterordner, dateien in os.walk(durchlaufe):
        for dateinamen in dateien:
            extension = os.path.splitext(dateinamen)[1]
            if extension == endung:
                if auswahl == "alphabetisch":
                    zeitpunkt = os.path.getctime(os.path.join(verzeichnisse, dateinamen))
                    fuelledict = {os.path.join(verzeichnisse, dateinamen) : zeitpunkt}
                    file_dict.update(fuelledict)
                elif auswahl == "angelegt":
                    zeitpunkt = os.path.getctime(os.path.join(verzeichnisse, dateinamen))
                elif auswahl == "aenderung":
                    zeitpunkt = os.path.getmtime(os.path.join(verzeichnisse, dateinamen))
                elif auswahl == "aufgerufen":
                    zeitpunkt = os.path.getatime(os.path.join(verzeichnisse, dateinamen))

                if auswahl == "angelegt" or auswahl == "aenderung" or auswahl == "aufgerufen":
                    if vondate == "-" or bisdate == "-":
                        fuelledict = {zeitpunkt : os.path.join(verzeichnisse, dateinamen)}
                        file_dict.update(fuelledict)
                    elif vondate != "-" and bisdate  != "-":
                        if zeitpunkt >= wandle_datum(vondate) and zeitpunkt <= wandle_datum(bisdate):
                            fuelledict = {zeitpunkt : os.path.join(verzeichnisse, dateinamen)}
                            file_dict.update(fuelledict)

    # Reihenfolge - files und filetimes - plus lambda und lower
    if auswahl == "alphabetisch":
        sortiert = sorted(file_dict.items(), key = lambda i: i[0].lower(), reverse = 1)
        
        for files, filetimes in sortiert:
            zeitformat = time.strftime("%d.%m.%Y", time.localtime(filetimes))
            rueckgabe.append("{0:s} - {1:s}".format(files, zeitformat))

    # Reihenfolge - filetimes und files
    elif auswahl == "angelegt" or auswahl == "aenderung" or auswahl == "aufgerufen":
        sortiert = sorted(file_dict.items(), reverse = 1)
        
        for filetimes, files in sortiert:
            zeitformat = time.strftime("%d.%m.%Y", time.localtime(filetimes))
            rueckgabe.append("{0:s} - {1:s}".format(files, zeitformat))

    return rueckgabe

class Dateisuche:

    def __init__(self):
        self.fenster = Tk()
        self.set_auswahl = StringVar(value="1")
        self.set_endung  = StringVar(value="1")
        self.textfeld = None
        self.auswahl = "alphabetisch"
        self.endung  = "py"
        self.vondate = None
        self.bisdate = None
        self.durchlaufe = "."

    def main(self):
         if self.vondate is None or self.vondate == "":
             self.vondate = "-"
         if self.bisdate is None or self.bisdate == "":
             self.bisdate = "-"
             
         gefunden = suche_files(self.durchlaufe, self.auswahl,
                    self.endung, self.vondate, self.bisdate)

         self.textfeld.delete(1.0, END)

         for dateien in gefunden:
             self.textfeld.insert(1.0, "{}\n".format(dateien))

# Der rest vom Code ist unverändert. 
TuXX
User
Beiträge: 19
Registriert: Sonntag 25. Juni 2017, 17:52

Dienstag 4. Juli 2017, 19:27

Erst einmal vielen Dank für das rege Feedback auf meine Frage. Mittlerweile bin ich mit meinem Skript etwas weiter gekommen. Siehe Beispiel:

Code: Alles auswählen

import os
for folderName, subfolders, filenames in os.walk('C:\\Techdok\\'):
    texfile = open ('Verzeichnislist.txt', 'a')
    texfile.write(folderName + "\n")
    for subfolder in subfolders:
        texfile.write(subfolder + "\n")
    for filename in filenames:
        texfile.write(filename + "\n")
    texfile.close()
Dieses Skript gibt folgendes aus:

C:\Techdok (hier müssen noch die ersten drei Zeichen entfernt werden, damit ich ein schönes erstes Lesezeichen kreiren kann!)
C.\Techdok\Ordner 1 (hier kann ich für das Unterlesezeichen nur den hintersten Ordner (in diesem Fall Ordner 1 gebrauchen)
Datei.pdf (hier müssen ebenfalls wieder die letzten vier Zeichnen entfernt werden, um ein schickes Lesezeichen zu haben)

Aktuell habe ich noch keine Lösung dafür gefunden, wie ich Pfade wie z.B. C:\Techdoc\Ordner1\Datei1.pdf in eine Datei schreiben kann. Wie sieht es bei den für Tex notwendigen geschweiften und eckigen Klammern aus. Gibt es hier eine spezielle Darstellungsweise um diese korrekt in eine Datei schreiben zu können?

Im Voraus vielen Dank für euren Input!
Zuletzt geändert von Anonymous am Dienstag 4. Juli 2017, 22:00, insgesamt 1-mal geändert.
Grund: Quelltext in Python-Codebox-Tags gesetzt.
BlackJack

Dienstag 4. Juli 2017, 22:10

@TuXX: Warum öffnest und schliesst Du denn die Datei für jedes Verzeichnis? Es wäre irgendwie sinnvoller die einmal am Anfang zu öffnen und dann am Ende zu schliessen. Das hattest Du doch auch schon mal so. Am besten verwendet man beim Öffnen die ``with``-Anweisung, damit die Datei automatisch und sicher geschlossen wird wenn der Programmfluss den ``with``-Block verlässt.

Wie das mit dem zusammensetzen von Pfaden geht, wurde hier im Thema auch schon gezeigt. Melewo hat da einen Beispielcode gezeigt, der zudem auch schon das filtern nach PDF-Dateien enthält.

Eckige und geschweifte Klammern in eine Datei zu schreiben ist kein Hexenwerk. Wo ist denn das Problem dabei? Ein tatsächliches Problem ist eher sicherzustellen das Zeichen die für LaTeX eine besondere Bedeutung haben, keine Probleme machen wenn sie in normalen Daten vorkommen. Dazu kann man sich selbst eine Funktion schreiben die solche Zeichen vor LaTeX entsprechend schützt, oder etwas fertiges hernehmen. Aber das hatten wir ja auch schon mal angesprochen.

Ist Dir denn das Ziel schon klar? Denn sonst kannst Du nicht darauf hinarbeiten.
Melewo
User
Beiträge: 320
Registriert: Mittwoch 3. Mai 2017, 16:30

Mittwoch 5. Juli 2017, 08:16

TuXX hat geschrieben:C:\Techdok (hier müssen noch die ersten drei Zeichen entfernt werden, damit ich ein schönes erstes Lesezeichen kreiren kann!)
C.\Techdok\Ordner 1 (hier kann ich für das Unterlesezeichen nur den hintersten Ordner (in diesem Fall Ordner 1 gebrauchen)
Datei.pdf (hier müssen ebenfalls wieder die letzten vier Zeichnen entfernt werden, um ein schickes Lesezeichen zu haben)
Dafür verwende ich bisher replace(). Bei immer gleichbleibenden Zeichenfolgen scheint es mir die einfachste Lösung zu sein. Ob die beste, weiß ich hingegen noch nicht, wäre nur meine Antwort auf Zeile 1 und 3 vom Zitat.

Code: Alles auswählen

beispiel = "beispieldatei.pdf"
ausgabe = "# Ausgabe: {0:s}".format(beispiel.replace(".pdf", ""))

print(ausgabe)
# Ausgabe: beispieldatei
Und den Codeabschnitt habe ich oben noch herausgekürzt, da der nur einmal benötigt wird und in einer Variablen gespeichert werden kann, die die dann für alle anderen Statements benutzt wird.

Code: Alles auswählen

os.path.join(verzeichnisse, dateinamen)
BlackJack

Mittwoch 5. Juli 2017, 08:42

@Melewo: `replace()` ersetzt alle vorkommen, auch innerhalb der Zeichenkette, ist also nicht die passende Operation um am Ende eine gewisse Anzahl von Zeichen zu entfernen. Da würde ich „slicing“ (``beispiel[:-len('.pdf')]``) oder `os.path.splitext()` verwenden.
Melewo
User
Beiträge: 320
Registriert: Mittwoch 3. Mai 2017, 16:30

Mittwoch 5. Juli 2017, 09:18

@BlackJack: Danke, musste ich doch gleich einmal probieren.

Code: Alles auswählen

beispiel = ".\\beispieldatei.pdf"
ausgabe = "# Ausgabe: {0:s}".format(beispiel[2:-4])

print(ausgabe)
# Ausgabe: beispieldatei

ausgabe = "# Ausgabe: {0:s}".format(beispiel[len('.\\'):-len('.pdf')])

print(ausgabe)
# Ausgabe: beispieldatei
BlackJack

Mittwoch 5. Juli 2017, 10:41

@Melewo: Da ist jetzt der Anfang nicht wirklich robust. Dafür würde ich `os.path.basename()` verwenden.

Code: Alles auswählen

>>> PDF_EXTENSION
'.pdf'
>>> beispiel
'./beispieldatei.pdf'
>>> os.path.basename(beispiel)[:-len(PDF_EXTENSION) if beispiel.endswith(PDF_EXTENSION) else None]
'beispieldatei'
Melewo
User
Beiträge: 320
Registriert: Mittwoch 3. Mai 2017, 16:30

Mittwoch 5. Juli 2017, 11:21

Ja, das sieht besser aus und ich nehme an, dass TuXX das ".\\" auch mit den ersten drei Zeichen meinte, die er entfernt haben möchte.
BlackJack

Mittwoch 5. Juli 2017, 11:47

Falls zu dem Zeitpunkt das *.pdf keine Rolle mehr spielt, weil generell alle Endungen entfernt werden sollen, oder es sowieso nur noch *.pdf's sind, würde ich es so schreiben (und in eine Funktion verpacken):

Code: Alles auswählen

>>> os.path.splitext(os.path.basename(beispiel))[0]
'beispieldatei'
TuXX
User
Beiträge: 19
Registriert: Sonntag 25. Juni 2017, 17:52

Mittwoch 5. Juli 2017, 19:37

Schrittchen für Schrittchen komme ich einer Lösung näher, allerdings nimmt die Zahl der Fragen nicht ab. Der aktuelle Stand der Software ist folgender:

Code: Alles auswählen

import os
for folderName, subfolders, filenames in os.walk('C:\\Techdok\\'):
    texfile = open ('Verzeichnislist.txt', 'a')
    texfile.write(folderName + "\n")
    for subfolder in subfolders:
        # Abtrennen des letzten Ordners aus dem Pfad
        
        texfile.write(subfolder + "\n")
    for filename in filenames:
        # Trennen des Dateinamens und Dateiendung über die Funktion os.path.splitext. Das Tupel 0 enthält den Dateinamen, während 1 die Endung enthält.
        file = os.path.splitext(filename)[0]
        # Schreiben des Dateinamens ohne Dateiendung
        texfile.write(file + "\n")
    texfile.close()
Trotz dem Studium unzähliger Homepages und Büchern konnte ich bisher keine Lösung dafür finden, wie ich auf einfache Weise den letzten Ordnername von subfolder auslesen kann. Gibt es hierfür überhaupt einen Python-Befehl. Sozusagen einen umgekehrten os.patch.join? Für subfolder wird z.B. c:\Techdok\Ordner1 ausgegeben. Wie kann ich nun Ordner1 extrahieren?
Zuletzt geändert von Anonymous am Mittwoch 5. Juli 2017, 20:11, insgesamt 1-mal geändert.
Grund: Quelltext in Python-Codebox-Tags gesetzt.
Sirius3
User
Beiträge: 8423
Registriert: Sonntag 21. Oktober 2012, 17:20

Mittwoch 5. Juli 2017, 20:07

@TuXX: es gibt os.path.basename dafür. Die Datei sollte immer noch vor der for-Schleife geöffnet werden.
BlackJack

Mittwoch 5. Juli 2017, 20:15

Wobei das gar nicht sein kann das `subfolder` in dem gezeigten Code mehr als eine Pfadkomponente enthält. Es würde keinen Sinn machen `os.path.basename()` darauf anzuwenden.
TuXX
User
Beiträge: 19
Registriert: Sonntag 25. Juni 2017, 17:52

Mittwoch 5. Juli 2017, 20:36

Die Ausgabe des veröffentlichten Codes ist die Folgende;

C:\Techdok\
Ordner1
Ordner2
Ordner3
C:\Techdok\Ordner1 (hier möchte ich nur Ordner 1 ausgeben!)
Datei1
Datei2
C:\Techdok\Ordner2 (hier möchte ich nur Ordner 2 ausgeben!)
Datei1
C:\Techdok\Ordner3 (hier möchte ich nur Ordner 3 ausgeben!)
Datei1
Datei2
Datei3
Datei4
Melewo
User
Beiträge: 320
Registriert: Mittwoch 3. Mai 2017, 16:30

Mittwoch 5. Juli 2017, 20:39

Da wurden doch nun bereits mehr Beispiele als genug gezeigt und ehrlich gesagt verstehe ich nicht das Problem. Ob Pfad oder String, alles lässt sich doch zerlegen und gerade habe ich z.B. festgestellt, dass sich relpath auch gut geeignet hätte, um die ersten 3 Zeichen loszuwerden. Mag sein, dass meine Beispiele nicht die besten sind und Schwachstellen haben, doch es wird wohl nun allgemein nicht anders sein, dass man erst einmal eine längere Zeit Lernen muss und Du wirst halt im ersten Jahr auch noch keine fehlerfreie Anwendung schreiben.

Und wenn Du den vierten nicht ausgeben möchtest, warum machst Du es dann, statt einen Tupel oder eine Liste mit gesperrten Verzeichnissen oder Dateien abzufragen?

Code: Alles auswählen

beispiel = ".\\verzeichnis\\beispiel.py"

print("# Ausgabe: {}".format(os.path.splitext(os.path.basename(beispiel))[0]))
print("# Ausgabe: {}".format(os.path.relpath(beispiel)))
print("# Ausgabe: {}".format(beispiel.split("\\")[1]))

# Ausgabe: beispiel
# Ausgabe: verzeichnis\beispiel.py
# Ausgabe: verzeichnis

beispiel = ".\\verzeichnis1\\verzeichnis2\\beispiel.py"

print("# Ausgabe: {}".format(os.path.splitext(os.path.basename(beispiel))[0]))
print("# Ausgabe: {}".format(os.path.relpath(beispiel)))
print("# Ausgabe: {}".format(beispiel.split("\\")[1]))
print("# Ausgabe: {}".format(beispiel.split("\\")[2]))

# Ausgabe: beispiel
# Ausgabe: verzeichnis1\verzeichnis2\beispiel.py
# Ausgabe: verzeichnis1
# Ausgabe: verzeichnis2
Melewo
User
Beiträge: 320
Registriert: Mittwoch 3. Mai 2017, 16:30

Mittwoch 5. Juli 2017, 21:37

Oben frage ich noch eine einzelne Endung ab.

Code: Alles auswählen

if extension == endung:
In der Zwischenzeit frage ich an dieser Stelle eine Liste mit Endungen ab, um auch zwei oder drei Endungen auswählen und übergeben zu können.

Code: Alles auswählen

if extension in endungsliste:
Und genauso kannst Du das in Verbindung mit not für eine Liste von gesperrten Dateien oder Verzeichnissen machen. Für Verzeichnisse musst Du Dir halt die richtige Stelle suchen, wo Du die Abfrage platzierst.

Code: Alles auswählen

liste = ["datei-31.pdf", "datei-32.pdf", "datei-45.pdf"]

datei = "datei-68.pdf"

if not (datei in liste):
    print("# Ausgabe: Die Datei {} ist nicht in der Liste enthalten.".format(datei))
else:
    print("# Ausgabe: Die Datei {} ist in der Liste enthalten.".format(datei))
    
datei = "datei-32.pdf"

if not (datei in liste):
    print("# Ausgabe: Die Datei {} ist nicht in der Liste enthalten.".format(datei))
else:
    print("# Ausgabe: Die Datei {} ist in der Liste enthalten.".format(datei))


# Ausgabe: Die Datei datei-68.pdf ist nicht in der Liste enthalten.
# Ausgabe: Die Datei datei-32.pdf ist in der Liste enthalten.
Antworten