web-dev-qa-db-fra.com

Obtenir une liste filtrée de fichiers dans un répertoire

J'essaie d'obtenir une liste de fichiers dans un répertoire en utilisant Python, mais je ne veux pas d'une liste de TOUS les fichiers.

Ce que je veux essentiellement, c’est pouvoir faire quelque chose comme ce qui suit, mais utiliser Python et ne pas exécuter ls.

ls 145592*.jpg

S'il n'y a pas de méthode intégrée à cela, je songe actuellement à écrire une boucle for pour parcourir les résultats d'une os.listdir() et pour ajouter tous les fichiers correspondants à une nouvelle liste.

Cependant, il y a beaucoup de fichiers dans ce répertoire et j'espère donc qu'il existe une méthode plus efficace (ou une méthode intégrée).

203
mhost
296

glob.glob() est définitivement le moyen de le faire (selon Ignacio). Cependant, si vous avez besoin d'une correspondance plus complexe, vous pouvez le faire avec une liste comprenant et une re.match(), comme ceci:

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

Plus flexible, mais comme vous le constatez, moins efficace.

102
Ben Hoyt

Rester simple:

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

Je préfère cette forme de compréhension de liste car elle se lit bien en anglais.

J'ai lu la quatrième ligne comme suit: Pour chaque fn de os.listdir de mon chemin, donnez-moi uniquement ceux qui correspondent à l'une de mes extensions incluses.

Il peut être difficile pour les novices programmeurs python de s’habituer réellement à l’utilisation de la compréhension de liste pour le filtrage. De surcroît, il peut y avoir une surcharge de mémoire pour les très grands ensembles de données, mais pour lister un répertoire et d’autres tâches simples de filtrage de chaînes, code documentable.

La seule chose à propos de cette conception est qu'elle ne vous protège pas contre l'erreur de passer une chaîne au lieu d'une liste. Par exemple, si vous convertissez accidentellement une chaîne en liste et finissez par vérifier tous les caractères d'une chaîne, vous risquez de générer une multitude de faux positifs.

Mais il est préférable d’avoir un problème facile à résoudre qu’une solution difficile à comprendre.

35
ramsey0

Une autre option:

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

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

29
Risadinha

utilisez os.walk pour lister vos fichiers de manière récursive

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
ghostdog74

Code préliminaire

import glob
import fnmatch
import pathlib
import os

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

Solution 1 - utilisez "glob"

# lookup in current dir
glob.glob(pattern)

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

Solution 2 - utilise "os" + "fnmatch"

Variant 2.1 - Recherche dans le répertoire actuel

# 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']

Variante 2.2 - Recherche récursive

# 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))

Résultat

./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

Solution 3 - utilise "pathlib"

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

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

Remarques:

  1. Testé sur le Python 3.4
  2. Le module "pathlib" a été ajouté uniquement dans Python 3.4
  3. Python 3.5 a ajouté une fonctionnalité de recherche récursive avec glob.glob https://docs.python.org/3.5/library/glob.html#glob.glob . Depuis que ma machine est installée avec Python 3.4, je n’ai pas testé cela.
7
Seti Volkylany

Filtrer avec le module glob:

Import Glob

import glob

Wild Cards:

files=glob.glob("data/*")
print(files)

Out:

['data/ks_10000_0', 'data/ks_1000_0', 'data/ks_100_0', 'data/ks_100_1',
'data/ks_100_2', 'data/ks_106_0', 'data/ks_19_0', 'data/ks_200_0', 'data/ks_200_1', 
'data/ks_300_0', 'data/ks_30_0', 'data/ks_400_0', 'data/ks_40_0', 'data/ks_45_0', 
'data/ks_4_0', 'data/ks_500_0', 'data/ks_50_0', 'data/ks_50_1', 'data/ks_60_0', 
'data/ks_82_0', 'data/ks_lecture_dp_1', 'data/ks_lecture_dp_2']

Extension de filtre .txt:

files = glob.glob("/home/ach/*/*.txt")

Un seul personnage

glob.glob("/home/ach/file?.txt")

Tranches de nombres

glob.glob("/home/ach/*[0-9]*")

Alphabet Ranges

glob.glob("/home/ach/[a-c]*")
4
pink.slash
import os

dir="/path/to/dir"
[x[0]+"/"+f for x in os.walk(dir) for f in x[2] if f.endswith(".jpg")]

Cela vous donnera une liste de fichiers jpg avec leur chemin complet. Vous pouvez remplacer x[0]+"/"+f par f pour les noms de fichiers uniquement. Vous pouvez également remplacer f.endswith(".jpg") par la condition de chaîne souhaitée.

2
EvgenijM86

vous pourriez aussi aimer une approche de plus haut niveau (j'ai implémenté et empaqueté comme 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

peut être installé avec

pip install findtools
2

Noms de fichiers avec les extensions "jpg" et "png" dans "path/to/images":

import os
accepted_extensions = ["jpg", "png"]
filenames = [fn for fn in os.listdir("path/to/images") if fn.split(".")[-1] in accepted_extensions]
1
gypsy

Vous pouvez utiliser subprocess.check_ouput () comme

import subprocess

list_files = subprocess.check_output("ls 145992*.jpg", Shell=True) 

Bien entendu, la chaîne entre guillemets peut correspondre à tout ce que vous voulez exécuter dans le shell et stocker le résultat.

0
David A.