Ordnerstrukturen auf Aktualisierung prüfen
Hallo,
ich habe einen USB-Stick E:\ dieser enthält einen Ordner 1, E:\1\
Dieser Ordner 1 enthält dann Unterordner A, B, C, E:\1\B\.
dort sind dann txt-Dateien a, b, c enthalten, welche auch aktualisiert oder hinzugefügt werden, E:\1\B\a.txt
Ich würde gerne ein Programm schreiben, welches alle Unterordner aus 1 durchsucht, ob es neue txt-Dateien gibt. Sollte dies der Fall sein, würde ich die Dateinamen gerne angezeigt bekommen.
Wie gehe ich da am sinnvollsten ran? Einfach E:\1\ prüfen entfällt, da dieser nicht zwangsweise als aktualisiert gekennzeichnet wird. Zumindest wenn ich es über time? lösen würde.
Ich bin für jedes Stichwort oder Idee dankbar
Oder ist diese Idee so garnichtumsetzbar?
Danke euch!
ich habe einen USB-Stick E:\ dieser enthält einen Ordner 1, E:\1\
Dieser Ordner 1 enthält dann Unterordner A, B, C, E:\1\B\.
dort sind dann txt-Dateien a, b, c enthalten, welche auch aktualisiert oder hinzugefügt werden, E:\1\B\a.txt
Ich würde gerne ein Programm schreiben, welches alle Unterordner aus 1 durchsucht, ob es neue txt-Dateien gibt. Sollte dies der Fall sein, würde ich die Dateinamen gerne angezeigt bekommen.
Wie gehe ich da am sinnvollsten ran? Einfach E:\1\ prüfen entfällt, da dieser nicht zwangsweise als aktualisiert gekennzeichnet wird. Zumindest wenn ich es über time? lösen würde.
Ich bin für jedes Stichwort oder Idee dankbar
Oder ist diese Idee so garnichtumsetzbar?
Danke euch!
-
- User
- Beiträge: 31
- Registriert: Samstag 16. Mai 2020, 18:52
Das einfachste wäre vermutlich den Ordner komplett zu durchsuchen "Path().rglob(".txt")". Und dieses Ergebnis dann zu speichern/vergleichen mit dem letzten Ergebnis.
Und wenn jetzt der Änderungszeitpunkt der Dateien wichtig ist, kann man den ja auch speichern "Path().stat().st_ctime".
Und wenn jetzt der Änderungszeitpunkt der Dateien wichtig ist, kann man den ja auch speichern "Path().stat().st_ctime".
okay, danke Dir schonmal für den Tipp.
Habe das erstmal so umgesetzt:
Leider ist das Ergebnis immer "neu", auch wenn ich die Liste my_match vor die Schleife packe.
Da die Suche ja immer aktuell durchgeführt wird, genauso wie das Schreiben der Liste, gibt es ja keine "alte Liste" oder?
Bisher habe ich dazu noch nichts gefunden, ich bin aber mal auf der Suche.
Habe das erstmal so umgesetzt:
Code: Alles auswählen
import os
from pathlib import Path
folder = Path(r'C:\Users\Admin\Documents\Python_Scripts')
file = Path(r'C:\Users\Admin\Documents\Python_Scripts\Hallo1.txt')
#datasize = os.path.getsize(folder)
#print(datasize)
#files = list(folder.rglob('*.txt'))
#print(files)
for file in list(folder.rglob('*.txt')):
my_match = []
match = my_match.append(file)
if match != my_match:
print("neu")
Da die Suche ja immer aktuell durchgeführt wird, genauso wie das Schreiben der Liste, gibt es ja keine "alte Liste" oder?
Bisher habe ich dazu noch nichts gefunden, ich bin aber mal auf der Suche.
-
- User
- Beiträge: 31
- Registriert: Samstag 16. Mai 2020, 18:52
Code: Alles auswählen
for file in list(folder.rglob('*.txt')):
my_match = []
match = my_match.append(file)
Und dann speicherst du die Antwort von der Append-Funktion die ein None zurück gibt, als match.
Wird die Schleife dann nach der letzten Textdatei verlassen. Ist die Liste unzählige male neu erstellt worden, aber enthält immer noch nur die letzte Datei aus der For-Schleife.
Und match ist natürlich None. Deswegen kann match nie my_match sein.
Und folder.rglob() ist eine Generator-Funktion die nicht extra als Liste umgewandelt werden muss, wenn man sie in einem For-Loop benutzt.
Ohne das Benutzen einer Temp-Datei in der die Files aufgelistet sind, könnte das so aussehen:
Code: Alles auswählen
from pathlib import Path
from time import sleep
def main():
WATCH_DIR = Path('C:/Users/Admin/Documents/Python_Scripts')
text_files = []
while True:
if not text_files:
text_files = [file for file in WATCH_DIR.rglob("*.txt")]
print("Erster Scan...")
else:
for file in WATCH_DIR.rglob("*.txt"):
if file not in text_files:
print(f"{file} ist neu.")
text_files.append(file)
sleep(5)
if __name__ == "__main__":
main()
- __blackjack__
- User
- Beiträge: 13111
- Registriert: Samstag 2. Juni 2018, 10:21
- Wohnort: 127.0.0.1
- Kontaktdaten:
@ElektroBerry: Das hat aber in bestimmten Situationen ein komisches Verhalten. Wenn beispielsweise am Anfang gar keine Dateien vorhanden sind, dann wird immer wieder "Erster Scan..." ausgegeben auch wenn es gar nicht mehr der erste Scan ist. Den ersten Scan würde man *vor* der Schleife machen.
Und ich würde da statt einer Liste auch eher ein `set()` verwenden.
Und ich würde da statt einer Liste auch eher ein `set()` verwenden.
„All religions are the same: religion is basically guilt, with different holidays.” — Cathy Ladman
-
- User
- Beiträge: 31
- Registriert: Samstag 16. Mai 2020, 18:52
Stimmt.
Also mal die Punkte verbessert:
Also mal die Punkte verbessert:
Code: Alles auswählen
from pathlib import Path
from time import sleep
def main():
WATCH_DIR = Path('C:/Users/Admin/Documents/Python_Scripts')
print("Erster Scan...")
text_files = set([file for file in WATCH_DIR.rglob("*.txt")])
while True:
for file in WATCH_DIR.rglob("*.txt"):
if file not in text_files:
print(f"{file} ist neu.")
text_files.add(file)
if not text_files:
print("Keine Datei gefunden.")
sleep(5)
if __name__ == "__main__":
main()
@ElektroBerry: um ein Set zu erzeugen braucht man nicht erst eine Liste.
Und der Generatorausdruck tut nichts, kann also auch weggelassen werden:
Code: Alles auswählen
text_files = set(file for file in WATCH_DIR.rglob("*.txt"))
Code: Alles auswählen
text_files = set(WATCH_DIR.rglob("*.txt"))
Ich danke euch zweien!
Wenn ich die if-Anfrage passend erweitere baue ich noch ein "wurde aktualisert" und "wurde entfernt" ein.
Anschließend versuche ich dann mal die "neuen/aktualisierten" Dateien zu verschieben/kopieren.
Grüße
Wenn ich die if-Anfrage passend erweitere baue ich noch ein "wurde aktualisert" und "wurde entfernt" ein.
Anschließend versuche ich dann mal die "neuen/aktualisierten" Dateien zu verschieben/kopieren.
Grüße
Die Probleme mit ganz neu, sowie gelöscht habe ich nun gelöst
Nun wollte ich gerne auf Aktualisierung prüfen, dazu wollte ich erstmal die Zeiten der file mit dem des sets vergleichen.
Nunja da gibts den ersten Error
TypeError: stat: path should be string, bytes, os.PathLike or integer, not set
wenn ich das ganze mir als Liste geben lasse, die Vorschläge gab es ja oben auch, erhalte ich selbigen Fehler.
Die Zeit der File kann ich aber doch nicht direkt vergleichen, da die file nur einmal abgefragt wird oder?
Hinter der Schleife würde ich dann die passende Zeitabfrage stellen, mMn
Vielleicht übersehe ich aber auch etwas.
Grüße
Nun wollte ich gerne auf Aktualisierung prüfen, dazu wollte ich erstmal die Zeiten der file mit dem des sets vergleichen.
Nunja da gibts den ersten Error
TypeError: stat: path should be string, bytes, os.PathLike or integer, not set
wenn ich das ganze mir als Liste geben lasse, die Vorschläge gab es ja oben auch, erhalte ich selbigen Fehler.
Die Zeit der File kann ich aber doch nicht direkt vergleichen, da die file nur einmal abgefragt wird oder?
Code: Alles auswählen
for file in FOLDER.rglob("*.txt") and text_files:
Vielleicht übersehe ich aber auch etwas.
Grüße
Bitte den gesamten Code und die komplette Fehlermeldung angeben.
Der Fehler ist doch offensichtlich. Du versuchst stat mit einem Set aufzurufen, was natürlich keinen Sinn ergibt.
Dass Du os.stat aufrufst, ist eh ein Fehler, da Du mit pathlib arbeitest und daher über die Variable `file` `file.stat()` benutzen solltest.
Der Fehler ist doch offensichtlich. Du versuchst stat mit einem Set aufzurufen, was natürlich keinen Sinn ergibt.
Dass Du os.stat aufrufst, ist eh ein Fehler, da Du mit pathlib arbeitest und daher über die Variable `file` `file.stat()` benutzen solltest.
Code: Alles auswählen
import os
from pathlib import Path
from time import sleep
import time
FOLDER = Path(r')
print("Erster Scan")
text_files = (set(FOLDER.rglob("*.txt")))
i = 0
while True:
for file in FOLDER.rglob("*.txt"):
if file not in text_files:
print(f"{file} ist neu")
text_files.add(file)
for file in text_files:
if file not in FOLDER.rglob("*.txt"):
print(f"{file} gelöscht")
text_files = set(FOLDER.rglob("*.txt"))
for file in FOLDER.rglob("*.txt") and text_files:
print(f"{file} aktualisiert")
if not text_files:
print("Keine Daten enthalten")
i = i + 1
print("Lauf", i)
sleep(5)
das ist der aktuelle Code, eigentlich wie oben.
Und wie lautet die komplette Fehlermeldung inklusive Traceback? An welcher Stelle tritt dieser Fehler auf?
Es ist Verschwendung, drei mal pro Durchlauf alle Dateien zu suchen.
Was soll eigentlich ´FOLDER.rglob("*.txt") and text_files` bedeuten? Was wolltest Du damit bewirken?
Wenn man zählen will, benutzt man eine for-Schleife und keine while-Schleife:
Es ist Verschwendung, drei mal pro Durchlauf alle Dateien zu suchen.
Was soll eigentlich ´FOLDER.rglob("*.txt") and text_files` bedeuten? Was wolltest Du damit bewirken?
Wenn man zählen will, benutzt man eine for-Schleife und keine while-Schleife:
Code: Alles auswählen
from pathlib import Path
from time import sleep
from itertools import count
FOLDER = Path('...')
print("Erster Scan")
previous_text_files = set(FOLDER.rglob("*.txt"))
for i in count(1):
text_files = set(FOLDER.rglob("*.txt"))
for filename in text_files - previous_text_files:
print(f"{filename} ist neu")
for filename in previous_text_files - text_files:
print(f"{filename} gelöscht")
previous_text_files = text_files
print("Lauf", i)
sleep(5)
mit dem dreimal durchsuchen, habe ich das Problem mit dem gelöscht gelöst, da sonst nicht aus der Ausgabe "gelöscht" herauskam.
mit dem ´FOLDER.rglob("*.txt") and text_files` wollte ich den letzten Fall durchgehen. Nämlich wenn eine Datei nur erneuert wird sind diese beiden identisch. Dadurch würde dann danach eine if-Abfrage folgen mit den Zeitstempel-Prüfung
mit dem ´FOLDER.rglob("*.txt") and text_files` wollte ich den letzten Fall durchgehen. Nämlich wenn eine Datei nur erneuert wird sind diese beiden identisch. Dadurch würde dann danach eine if-Abfrage folgen mit den Zeitstempel-Prüfung
Was läuft nicht permanent?
Die Tipps habe wir gegeben, aber die Umsetzung ist von Dir, und die Anforderungen ändern sich bei Dir ja auch bei jedem Post.
Wo Du den os.stat-Fehler her hast, hast Du aber immer noch nicht verraten.
Die Tipps habe wir gegeben, aber die Umsetzung ist von Dir, und die Anforderungen ändern sich bei Dir ja auch bei jedem Post.
Wo Du den os.stat-Fehler her hast, hast Du aber immer noch nicht verraten.
den os.stat-Fehler hatte ich, nachdem ich in meiner Logik das set mit dem stat (Path().stat().st_ctime) als Vorschlag von ElektroBerry kombinieren wollte.
Denn wenn sich die Zeit einer Datei ändert und diese mit dem ersten erstellten set verglichen wird, müsste dort ja die Änderung eintreten (diie Datei wurde aktualisiert?).
Das sich die Änderungen immer ändern liegt ja daran, dass ich das ganze nach und nach aufbaue und immer wieder teste, siehe die Meldung, dass eine Datei gelöscht wurde.
Nun ist die Frage, wenn eine aktuellere Dateio mit selben Namen kommt.
Das ich das ganze in einer while True-Schleife gebaut habe, kam ja nach dem Vorschlag von ElektroBerry. Ob ich den Durchlauf zähle oder nicht, dient hier nur zum erkennen, ob die Schleife wirklich läuft.
Denn wenn sich die Zeit einer Datei ändert und diese mit dem ersten erstellten set verglichen wird, müsste dort ja die Änderung eintreten (diie Datei wurde aktualisiert?).
Das sich die Änderungen immer ändern liegt ja daran, dass ich das ganze nach und nach aufbaue und immer wieder teste, siehe die Meldung, dass eine Datei gelöscht wurde.
Nun ist die Frage, wenn eine aktuellere Dateio mit selben Namen kommt.
Das ich das ganze in einer while True-Schleife gebaut habe, kam ja nach dem Vorschlag von ElektroBerry. Ob ich den Durchlauf zähle oder nicht, dient hier nur zum erkennen, ob die Schleife wirklich läuft.
Du hast ja schon einen stat-Aufruf von Path. Da macht es natürlich keinen Sinn, damit auch noch os.stat aufzurufen.
Und wie schon geschrieben, wenn man eine endlos-Schleife braucht nimmt man eine while-Schleife, wenn man aber einen Zähler braucht, ist halt eine for-Schleife besser.
Und wie schon geschrieben, wenn man eine endlos-Schleife braucht nimmt man eine while-Schleife, wenn man aber einen Zähler braucht, ist halt eine for-Schleife besser.
Okay, dann ist dies quasi Gesetz mit der while und for-Schleife, obwohl sie für den endlos Fall gleiches tun, danke.
Den stat-Aufruf habe ich ja bei dem set getestet, ohne Erfolg.
Beispeilsweise wäre ja hier nach dann der Fall, was passieren soll, wenn etwas "aktualisiert" wurde.
demnach würde ich hier hinter eine if-Bedingung mit einer Zeitabfrage der Datei einbauen müssen, weshalb ich wieder mit os.stat für die Datei arbeiten müsste, iwie sowas:
Das funktioniert so aber nicht, da ich keine weitere Abfrage einbaue, erweitere ich die Abfrage zu:
erhalte ich dauerhaft die Meldung, dass die Datei aktualisiert wurde.
Ich habe das ganze versucht in deinen Code miteinzubauen:
Wo liegt denn mein Denkfehler? oder kenne ich erfahrungsmäßig gewisse Methoden nicht?
Muss ich vllt nach der Abfrage bei gleichen Sets die Datei öffnen und Zeile für Zeile vergleichen lassen?
Falls ja, wie baue ich diese Variante für n Dateien um, was ich bei Goggle fand, war nur zu konkreten Dateien.
Danke für deine Hilfe
Den stat-Aufruf habe ich ja bei dem set getestet, ohne Erfolg.
Beispeilsweise wäre ja hier nach dann der Fall, was passieren soll, wenn etwas "aktualisiert" wurde.
Code: Alles auswählen
for filename in previous_text_files and text_files:
Code: Alles auswählen
os.stat(filename).st_atime
Code: Alles auswählen
if os.stat(filename in previous_text_files).st_atime != os.stat(filename in text_files).st_atime:
print(f"{filename} aktualisiert")
Ich habe das ganze versucht in deinen Code miteinzubauen:
Code: Alles auswählen
from pathlib import Path
from time import sleep
from itertools import count
FOLDER = Path('S:\Palkovits\intern\HPLC-Daten\Jens Heller')
print("Erster Scan")
previous_text_files = set(FOLDER.rglob("*.txt"))
for i in count(1):
print(os.stat(filename).st_atime)
text_files = set(FOLDER.rglob("*.txt"))
for filename in text_files - previous_text_files:
print(f"{filename} ist neu")
for filename in previous_text_files - text_files:
print(f"{filename} gelöscht")
for filename in previous_text_files and text_files:
if os.stat(filename in previous_text_files).st_atime != os.stat(filename in text_files).st_atime:
print(f"{filename} aktualisiert")
previous_text_files = text_files
print("Lauf", i)
sleep(5)
Muss ich vllt nach der Abfrage bei gleichen Sets die Datei öffnen und Zeile für Zeile vergleichen lassen?
Falls ja, wie baue ich diese Variante für n Dateien um, was ich bei Goggle fand, war nur zu konkreten Dateien.
Danke für deine Hilfe
Sie tun eben nicht das selbe. Im einen Fall hast Du einen Zähler, im anderen nicht.
Du kannst nicht Syntax raten und hoffen, dass es schon das macht, was Du hoffst. Hast Du Dir schonmal angeschaut, was der Ausdruck `previous_text_files and text_files` macht??Karlirex hat geschrieben: ↑Mittwoch 31. März 2021, 08:12Code: Alles auswählen
for filename in previous_text_files and text_files:
Genauso `filename in previous_text_files`! Was erwartest Du denn, was dieser Ausdruck innerhalb von os.stat macht? Und hast Du geprüft, was er wirklich macht?
Code baut man Stück für Stück auf, und testet jeden Schritt.
Also Dateien, die früher schon da waren und jetzt immer noch da sind, bekommt man über die Sets:
Code: Alles auswählen
kept_text_files = previous_text_files & text_files
Gar nicht. Deshalb mußt Du die Zeiten schon vorher bestimmen. Also neben dem Dateinamen auch die Änderungszeit speichern. Dazu bietet sich ein Wörterbuch an.
Code: Alles auswählen
def get_files_with_atime(folder):
return {
filename: filename.stat().st_atime
for filename in folder.rglob("*.txt")
}
Aber den Fall "kept_text_files", welchen du beschreibst, löst du doch genauso über das & (and), wie ich, nur dass du dem ganzen einen neuen Namen (kept_text_files) gibst. Also warum diese Änderung?
Auch wenn while/for etwas anderes darstellen, nach der Konvention, schreibe ich doch nicht 3x Code, nur damit ich dazwischen sehe, ob er wirklich durchläuft, sondern nehme dann nur die letzten Punkte aus der while-Schleife.
Den Fall, welche du mit der Funktion beschrieben hast, gibt doch erstmal den gesamten Ordner als Zeit aus, in einem Wörterbuch gespeichert, oder?
Ich gebe mich mit der ganzen Materie etwas schwer, dass mag sein. Leider komme ich aus keiner Programmierecke und erhalte halt die ein oder andere Idee und versuche mich dann daran. Wenn ich mir verschiedene Bücher dazu ansehe, fühle ich mich leider einfach nur erschlagen, gerade, weil es für eine Lösung eben 7 Wege gibt (siehe unser Schleifenthema).
Auch wenn while/for etwas anderes darstellen, nach der Konvention, schreibe ich doch nicht 3x Code, nur damit ich dazwischen sehe, ob er wirklich durchläuft, sondern nehme dann nur die letzten Punkte aus der while-Schleife.
Den Fall, welche du mit der Funktion beschrieben hast, gibt doch erstmal den gesamten Ordner als Zeit aus, in einem Wörterbuch gespeichert, oder?
Ich gebe mich mit der ganzen Materie etwas schwer, dass mag sein. Leider komme ich aus keiner Programmierecke und erhalte halt die ein oder andere Idee und versuche mich dann daran. Wenn ich mir verschiedene Bücher dazu ansehe, fühle ich mich leider einfach nur erschlagen, gerade, weil es für eine Lösung eben 7 Wege gibt (siehe unser Schleifenthema).