Vraag Download een gefilterde lijst met bestanden in een map


Ik probeer een lijst met bestanden in een map te krijgen met Python, maar ik wil geen lijst met ALLE bestanden.

Wat ik in essentie wil, is het vermogen om iets als het volgende te doen, maar Python te gebruiken en ls niet uit te voeren.

ls 145592*.jpg

Als er geen ingebouwde methode voor dit is, denk ik momenteel aan het schrijven van een for-lus om door de resultaten van een te herhalen os.listdir() en om alle overeenkomende bestanden aan een nieuwe lijst toe te voegen.

Er zijn echter veel bestanden in die map en daarom hoop ik dat er een efficiëntere methode is (of een ingebouwde methode).


176
2018-02-08 23:02


oorsprong


antwoorden:


glob.glob('145592*.jpg')


256
2018-02-08 23:05



glob.glob() is absoluut de manier om het te doen (zoals bij Ignacio). Als u echter meer gecompliceerde overeenkomsten nodig heeft, kunt u dit doen met een lijstbegrip en re.match(), zoiets als:

files = [f for f in os.listdir('.') if re.match(r'[0-9]+.*\.jpg', f)]

Flexibeler, maar zoals u merkt, minder efficiënt.


94
2018-02-09 00:27



Hou het simpel:

import os
relevant_path = "[path to folder]"
included_extenstions = ['jpg', 'bmp', 'png', 'gif']
file_names = [fn for fn in os.listdir(relevant_path)
              if any(fn.endswith(ext) for ext in included_extensions)]

Ik geef de voorkeur aan deze vorm van lijstbegrippen omdat deze goed in het Engels leest.

Ik heb de vierde regel gelezen als:   Geef voor elke fn in os.listdir voor mijn pad alleen degenen die overeenkomen met een van mijn opgenomen extensies.

Het is misschien moeilijk voor beginnende python-programmeurs om echt te wennen aan het gebruik van list comprehensions voor filteren, en het kan wat geheugenoverhead hebben voor zeer grote datasets, maar voor het vermelden van een directory en andere eenvoudige stringfilteringstaken leiden lijstbegrippen tot meer clean documenteerbare code.

Het enige aan dit ontwerp is dat het je niet beschermt tegen het maken van de fout een string door te geven in plaats van een lijst. Als u bijvoorbeeld per ongeluk een tekenreeks naar een lijst converteert en uiteindelijk controleert op alle tekens van een tekenreeks, krijgt u mogelijk een hoop valse positieven.

Maar het is beter om een ​​probleem te hebben dat gemakkelijk te repareren is dan een oplossing die moeilijk te begrijpen is.


29
2018-01-13 16:27



Andere optie:

>>> import os, fnmatch
>>> fnmatch.filter(os.listdir('.'), '*.py')
['manage.py']

https://docs.python.org/3/library/fnmatch.html


25
2018-01-28 11:55



gebruik os.walk om uw bestanden recursief weer te geven

import os
root = "/home"
pattern = "145992"
alist_filter = ['jpg','bmp','png','gif'] 
path=os.path.join(root,"mydir_to_scan")
for r,d,f in os.walk(path):
    for file in f:
        if file[-3:] in alist_filter and pattern in file:
            print os.path.join(root,file)

8
2018-02-09 01:46



Voorlopige code

import glob
import fnmatch
import pathlib
import os

pattern = '*.py'
path = '.'

Oplossing 1 - gebruik "glob"

# lookup in current dir
glob.glob(pattern)

In [2]: glob.glob(pattern)
Out[2]: ['wsgi.py', 'manage.py', 'tasks.py']

Oplossing 2 - gebruik "os" + "fnmatch"

Variant 2.1 - Opzoeken in huidig ​​richtsnoer

# lookup in current dir
fnmatch.filter(os.listdir(path), pattern)

In [3]: fnmatch.filter(os.listdir(path), pattern)
Out[3]: ['wsgi.py', 'manage.py', 'tasks.py']

Variant 2.2 - Lookup recursief

# lookup recursive
for dirpath, dirnames, filenames in os.walk(path):

    if not filenames:
        continue

    pythonic_files = fnmatch.filter(filenames, pattern)
    if pythonic_files:
        for file in pythonic_files:
            print('{}/{}'.format(dirpath, file))

Resultaat

./wsgi.py
./manage.py
./tasks.py
./temp/temp.py
./apps/diaries/urls.py
./apps/diaries/signals.py
./apps/diaries/actions.py
./apps/diaries/querysets.py
./apps/library/tests/test_forms.py
./apps/library/migrations/0001_initial.py
./apps/polls/views.py
./apps/polls/formsets.py
./apps/polls/reports.py
./apps/polls/admin.py

Oplossing 3 - gebruik "pathlib"

# lookup in current dir
path_ = pathlib.Path('.')
tuple(path_.glob(pattern))

# lookup recursive
tuple(path_.rglob(pattern))

Opmerkingen:

  1. Getest op de Python 3.4
  2. De module "pathlib" is alleen in de Python 3.4 toegevoegd
  3. De Python 3.5 heeft een functie toegevoegd voor recursieve lookup met glob.glob https://docs.python.org/3.5/library/glob.html#glob.glob. Aangezien mijn machine is geïnstalleerd met Python 3.4, heb ik dat niet getest.

4
2017-11-12 19:32



misschien hou je ook van een aanpak op hoger niveau (ik heb geïmplementeerd en verpakt zoals findtools):

from findtools.find_files import (find_files, Match)


# Recursively find all *.txt files in **/home/**
txt_files_pattern = Match(filetype='f', name='*.txt')
found_files = find_files(path='/home', match=txt_files_pattern)

for found_file in found_files:
    print found_file

kan worden geïnstalleerd met

pip install findtools

1
2018-05-29 22:13