Bestandsextensie-jokertekens gebruiken in os.listdir(pad)

Ik heb een map met bestanden die ik probeer te ontleden met Python. Ik zou geen probleem hebben als ze allemaal dezelfde extensie hadden, maar om welke reden dan ook zijn ze gemaakt met opeenvolgende numerieke extensies na hun oorspronkelijke extensie. Bijvoorbeeld: foo.log foo.log.1 foo.log.2 bar.log bar.log.1 bar.log.2 etc.Bovendien is foo.log in XML-formaat , terwijl bar.log dat niet is. Wat is de beste route om alleen de foo.log.*enfoo.logbestanden te lezen en te ontleden? De bar.logbestanden hoeven niet gelezen te worden. Hieronder is mijn code:

import os
from lxml import etree
path = 'C:/foo/bar//'
listing = os.listdir(path)
for files in listing:
    if files.endswith('.log'):
        print files
        data = open(os.path.join(path, files), 'rb').read()
        tree = etree.fromstring(data)
        search = tree.findall('.//QueueEntry')

Dit werkt niet omdat het geen .log.*-bestanden leest en de parser zich verslikt in de bestanden die worden gelezen, maar niet in xml-formaat. Bedankt!


Antwoord 1, autoriteit 100%

Misschien kan de module globu helpen:

import glob
listing = glob.glob('C:/foo/bar/foo.log*')
for filename in listing:
    # do stuff

Antwoord 2, autoriteit 14%

Wat is de beste route om alleen de bestanden foo.log.*en foo.logte lezen en te ontleden? De bar.log-bestanden hoeven niet te worden gelezen.

Uw code doet dit:

if files.endswith('.log'):

Je hebt zojuist je Engelse beschrijving een beetje verkeerd in Python vertaald. Wat je in Python schrijft is: “lees en ontleden alleen de *.logbestanden”, wat betekent dat bar.logis inbegrepen, en foo.log.1niet.

Maar als je even nadenkt, kun je je Engelse beschrijving direct in Python vertalen:

if files == 'foo.log' or files.startswith('foo.log.'):

En als je erover nadenkt, zolang er geen bestanden zijn met de naam foo.log.(met die extra stip) die je wilt overslaan, kun je de twee gevallen samenvouwen tot één:

if files.startswith('foo.log'):

Als je echter iets weet over POSIX-shells, foo.log*komt precies hetzelfde overeen. (Dat geldt niet voor Windows-shells, waar wildcards extensies speciaal behandelen, daarom moet je *.*typen in plaats van *.) En Python wordt geleverd met een module die gebruikt POSIX-achtige wildcards, zelfs op Windows, genaamd glob. Zie het antwoord van stranac voor hoe u dit kunt gebruiken.

Ik denk dat het antwoord globbeter is dan het handmatig filteren van listdir. Het is eenvoudiger, het komt directer overeen met wat de titel van uw vraag zegt dat u wilt doen (doe gewoon precies wat u hoopte dat zou werken met os.listdir, maar met glob.globin plaats daarvan), en het is flexibeler. Dus, tenzij je bang bent dat je in de war raakt door de twee enigszins verschillende betekenissen van jokertekens, raad ik je aan die te accepteren in plaats van deze.


Antwoord 3, autoriteit 6%

Hierdoor krijg je bash-achtige regexen:

import glob
print(glob.glob("/tmp/o*"))

U kunt ook de hele map os.listdir gebruiken en bestanden die niet overeenkomen met een regex weggooien via de re-module.


Antwoord 4

Zoals meerderen al zeiden: je zou glob.glob kunnen gebruiken om bestanden te vinden met behulp van jokertekens.
Ik kan geen commentaar schrijven en het is een heel oude vraag, maar… Iemand suggereerde dat de glob.glob niet kan uitbreiden ~ in het pad. U kunt er dus os.path.expanduser voor gebruiken, en os.path.expandvars om omgevingsvariabelen uit te breiden.

Other episodes