Hallo zusammen,
nehmen wir an ich habe einen Ordner in dem sich mehrere Datein befinden (z.B. Syslog1.txt, Syslog2.txt, Syslog2.txt ... ). Jetzt möchte ich nacheinander die Datein öffnen und Sie nach einer bestimmten Zeichenkette durchsuchen. Wie stell ich das an ?
Ziel soll sein alle Datein in denen sich die Zeichenkette befindet in einer Liste auszugeben.
Mehrere Datein in einem Ordner durchsuchen
- __blackjack__
- User
- Beiträge: 14076
- Registriert: Samstag 2. Juni 2018, 10:21
- Wohnort: 127.0.0.1
- Kontaktdaten:
Wobei komplettes einlesen von anscheinend Logdateien je nach Hauptspeicher- und Dateigrösse eventuell keine gute Idee ist. Falls der Text sich nicht über mehr als eine Zeile erstreckt, wäre es wahrscheinlich sinnvoller die Dateien zeilenweise zu verarbeiten. Dann kann man auch mit dem Lesen aufhören wenn man einen Treffer hatte. Die `any()`-Funktion könnte in dem Zusammenhang interessant sein.
“Vir, intelligence has nothing to do with politics!” — Londo Mollari
- DeaD_EyE
- User
- Beiträge: 1244
- Registriert: Sonntag 19. September 2010, 13:45
- Wohnort: Hagen
- Kontaktdaten:
Wenn die Logdateien größer sind als der RAM, hat der Admin des Systems ein ganz anderes Problem.
Normalerweise werden Logdateien ab einer bestimmten Größe rotiert.
Ab einer bestimmten Anzahl werden die ältesten Logdateien durch neuere überschrieben.
Dennoch ist das Zeilenweise lesen effizienter, da viele RAM gespart wird.
So kann man auch Dateien verarbeiten, die größer als der RAM und Festplatte zusammen sind.
Normalerweise werden Logdateien ab einer bestimmten Größe rotiert.
Ab einer bestimmten Anzahl werden die ältesten Logdateien durch neuere überschrieben.
Dennoch ist das Zeilenweise lesen effizienter, da viele RAM gespart wird.
So kann man auch Dateien verarbeiten, die größer als der RAM und Festplatte zusammen sind.
Code: Alles auswählen
import gzip
from pathlib import Path
def by_last_int(path: Path):
# Datei hat nur eine Endung: xyz.log
if len(path.suffixes) == 1:
return -1
# Datei hat zwei Endungen: xyz.log.0
elif len(path.suffixes) == 2:
return int(path.suffixes[-1].removeprefix("."))
# Datei hat drei Endungen: xyz.log.0.gz
elif len(path.suffixes) == 3:
return int(path.suffixes[-2].removeprefix("."))
MUSTER = "boot*"
PFAD = "/var/log"
TEXT = "Mounting"
log = Path(PFAD)
sorted_glob = sorted(log.glob(MUSTER), key=by_last_int)
for path in sorted_glob:
if path.is_dir():
# sollte niemals vorkommen,
# es seiden jemand erstellt mit Absicht
# ein Verzeichnis, dass dem Muster einer Logdatei entspricht
continue
if path.suffix == ".gz":
# mit gzip dekomprimieren
# der Text-Modus muss explizit mit angegeben werden,
# sonst bekommt man nur bytes
fd = gzip.open(path, "rt")
else:
# normale datei
# hier ist der Textmodus standardmaäßig wie bei open()
fd = path.open()
# fd ist entweder die geöffnete Datei
# oder die komprimierte geöffnete Datei
if any(TEXT in line for line in fd):
print("Treffer:", path)
sourceserver.info - sourceserver.info/wiki/ - ausgestorbener Support für HL2-Server
Vielen Dank für Eure Antworten,
Es dreht sich hier um Trace Datein von Gesprächen. Jede Datei ist 20 MB groß. Gesucht wird nach einer Rufnummer eines Gespräches welches sich durchaus über mehrer Datein hinziehen kann, je nach Gesprächslange. Die gefundenen Datein sollen Später dann zu einer zusammengefasst werden um den kompletten Call Flow in einer Datei zu haben.
DIe Any Funktion werde ich mir mal ansehen.
Es dreht sich hier um Trace Datein von Gesprächen. Jede Datei ist 20 MB groß. Gesucht wird nach einer Rufnummer eines Gespräches welches sich durchaus über mehrer Datein hinziehen kann, je nach Gesprächslange. Die gefundenen Datein sollen Später dann zu einer zusammengefasst werden um den kompletten Call Flow in einer Datei zu haben.
DIe Any Funktion werde ich mir mal ansehen.
- DeaD_EyE
- User
- Beiträge: 1244
- Registriert: Sonntag 19. September 2010, 13:45
- Wohnort: Hagen
- Kontaktdaten:
Das ist wie mit den Mappen von Bewerbern. Alles, das nicht schwarz oder weiß ist, kommt auf den Stapel, der an die Bewerber direkt zurückgeht. Die Personaler schauen da nicht rein.sparrow hat geschrieben: Montag 24. Oktober 2022, 20:02 @DeaD_EyE: Logdateien, die größer sind als der verfügbare Speicher, sind keine Seltenheit und lassen nicht auf Probleme des Admins schließen.
Ich habe genügend dedizierte Server gesehen und kann aus Erfahrung sagen, dass die Server mit exorbitant großen Logdateien fast nie gewartet werden und davon gibt es ganz viele.
Meistens sieht man das schon direkt beim Login via SSH. Wenn das schon ein Jahr her ist, dann weiß man, woran man ist.
Ich möchte nicht abstreiten, dass es gute Gründe geben kann, Logdateien so groß werden zu lassen.
Das ist aber nicht die Regel.
PS: Ja, ich weiß auch, dass es schon einigen Leuten den ARSCH gerettet hat, weil die MySQL-Datenbank brav geloggt hat. So konnten die dann ihre Datenbank wiederherstellen. Die Dateien sind auch groß.
sourceserver.info - sourceserver.info/wiki/ - ausgestorbener Support für HL2-Server
Hallo zusammen,
hier mein Code den ich bis jetzt erstellt habe. Funktioniert auch soweit.
der output sieht dan so aus:
Please enter text: 494213331120
L:\python\SBC10\Syslog_10.155.33.27_0001.txt
L:\python\SBC10\Syslog_10.155.33.27_0002.txt
L:\python\SBC10\Syslog_10.155.33.27_0004.txt
L:\python\SBC10\Syslog_10.155.33.27_0005.txt
Die gefundenen Datein sollen Später dann zu einer zusammengefasst werden um den kompletten Call Flow in einer Datei zu haben. Mom ist das ja lediglich ein print Befehl. wie würdet Ihr die abspeichern um sie dann zu bearbeiten
hier mein Code den ich bis jetzt erstellt habe. Funktioniert auch soweit.
Code: Alles auswählen
import os
text = input("Please enter text: ")
path = 'L:\python\SBC10'
def searchText(path):
os.chdir(path)
files = os.listdir()
for file_name in files:
abs_path = os.path.abspath(file_name)
if os.path.isdir(abs_path):
searchText(abs_path)
if os.path.isfile(abs_path):
with open(file_name, 'r') as f:
if text in f.read():
final_path = os.path.abspath(file_name)
print (final_path)
pass
Please enter text: 494213331120
L:\python\SBC10\Syslog_10.155.33.27_0001.txt
L:\python\SBC10\Syslog_10.155.33.27_0002.txt
L:\python\SBC10\Syslog_10.155.33.27_0004.txt
L:\python\SBC10\Syslog_10.155.33.27_0005.txt
Die gefundenen Datein sollen Später dann zu einer zusammengefasst werden um den kompletten Call Flow in einer Datei zu haben. Mom ist das ja lediglich ein print Befehl. wie würdet Ihr die abspeichern um sie dann zu bearbeiten
`os.chdir` darf man nicht verwenden, weil es global das Arbeitsverzeichnis ändert. Deshalb mußt Du auch diese Verrenkungen mit abspath machen, denn sonst funktioniert Dein rekursiver Aufruf nicht. `path` übergibst Du als Argument, aber `text` wird als globale Variable benutz? Warum?
Statt os benutzt man pathlib.Path. Statt rekursiver Aufruf benutzt man rglob. Kam hier aber alles schonmal vor.
Beim Öffnen von Textdateien muß man immer das korrekte Encoding angeben.
Wenn Du die Dateinamen nicht per print ausgeben willst, dann mach halt was anderes damit:
Statt os benutzt man pathlib.Path. Statt rekursiver Aufruf benutzt man rglob. Kam hier aber alles schonmal vor.
Beim Öffnen von Textdateien muß man immer das korrekte Encoding angeben.
Code: Alles auswählen
from pathlib import Path
PATH = Path('L:/python/SBC10')
def search_text(path, text):
for filename in path.rglob('*.txt'):
content = filename.read_text(encoding="ASCII")
if text in content:
print(filename)
Code: Alles auswählen
from pathlib import Path
PATH = Path('L:/python/SBC10')
def search_text(path, text):
for filename in path.rglob('*'):
if filename.is_file():
content = filename.read_text(encoding="ASCII")
if text in content:
yield filename
def main():
text = input("Please enter text: ")
filenames = list(search_text(PATH, text))
...
if __name__ == "__main__":
main()
- __blackjack__
- User
- Beiträge: 14076
- Registriert: Samstag 2. Juni 2018, 10:21
- Wohnort: 127.0.0.1
- Kontaktdaten:
An der Stelle eine kleine Warnung zur Dateireihenfolge: Es kann eventuell so aussehen, dass die Dateinamen/-pfade irgendwie sortiert geliefert werden, das ist aber ein Implementierungsdetail des Betriebssystems beziehungsweise dort noch mal vom jeweiligen Dateisystemtreiber.
Falls die Weiterverarbeitung nicht mehr funktionieren würde wenn man beispielsweise im letzten Beispiel von Sirius3 nach dem ermitteln von `filenames` noch ein ``random.shuffle(filenames)`` einfüügen würde, dann muss man die `filenames` explizit sortieren.
Falls die Weiterverarbeitung nicht mehr funktionieren würde wenn man beispielsweise im letzten Beispiel von Sirius3 nach dem ermitteln von `filenames` noch ein ``random.shuffle(filenames)`` einfüügen würde, dann muss man die `filenames` explizit sortieren.
“Vir, intelligence has nothing to do with politics!” — Londo Mollari
Ich hab s jetzt damit gelöst:
Code: Alles auswählen
for f in os.listdir(dst):
text = '\n'.join( open(os.path.join(dst,f)).readlines() )
if any([term in text for term in search_terms]):
print (f)
else:
- DeaD_EyE
- User
- Beiträge: 1244
- Registriert: Sonntag 19. September 2010, 13:45
- Wohnort: Hagen
- Kontaktdaten:
Aufgrund der falschen Annahme ist folgendes passiert: https://www.reddit.com/r/Python/comment ... es_may_be/__blackjack__ hat geschrieben: Dienstag 1. November 2022, 13:05 An der Stelle eine kleine Warnung zur Dateireihenfolge: Es kann eventuell so aussehen, dass die Dateinamen/-pfade irgendwie sortiert geliefert werden, das ist aber ein Implementierungsdetail des Betriebssystems beziehungsweise dort noch mal vom jeweiligen Dateisystemtreiber.
Unter Linux wird, soweit ich weiß, nach Inode-Nummern sortiert. Da auch Dateien auf dem Dateisystem gelöscht werden können, werden diese Inodes wieder frei und können neuen Dateien dann vergeben werden. Bei einem frisch installiertem Linux sieht es so aus, als ob die Dateien sortiert sind, was aber nur ein Nebeneffekt der frischen Installation ist. Die Installation fängt ja mit einem leeren Dateisystem an.
Die Sortierreihenfolge unter Windows ist mir aber nicht bekannt. Auch dort würde ich annehmen, dass die Reihenfolge nicht definiert ist.
Bezüglich der "Lösung"
Code: Alles auswählen
text = '\n'.join( open(os.path.join(dst,f)).readlines() )
Das liegt daran, dass die Dateien komplett in den RAM eingelesen werden. Dann werden die Zeilen geteilt, wodurch eine Liste mit Strings erstellt wird (doppelter Speicherverbrauch).
Dann kommt noch mal das Zusammenfügen des neuen Strings durch die join-Methode. Auch da bleibt der Inhalt so lange im Speicher, bis der finale String fertig ist und der Garbage-Collector die verwaisten Objekte entfernt hat.
sourceserver.info - sourceserver.info/wiki/ - ausgestorbener Support für HL2-Server