Znajdź wszystkie pliki w katalogu z rozszerzeniem .txt w Pythonie


Odpowiedzi:


2354

Możesz użyć glob:

import glob, os
os.chdir("/mydir")
for file in glob.glob("*.txt"):
    print(file)

lub po prostu os.listdir:

import os
for file in os.listdir("/mydir"):
    if file.endswith(".txt"):
        print(os.path.join("/mydir", file))

lub jeśli chcesz przejść przez katalog, użyj os.walk:

import os
for root, dirs, files in os.walk("/mydir"):
    for file in files:
        if file.endswith(".txt"):
             print(os.path.join(root, file))

11
Korzystając z rozwiązania nr 2, w jaki sposób utworzyłbyś plik lub listę z tymi informacjami?
Merlin

72
@ ghostdog74: Moim zdaniem bardziej odpowiednie byłoby pisanie for file in fniż dla, for files in fponieważ w zmiennej znajduje się pojedyncza nazwa pliku. Jeszcze lepiej byłoby, aby zmienić fsię files, a następnie do pętli może stać for file in files.
martineau

45
@computermacgyver: Nie, filenie jest słowem zastrzeżonym, tylko nazwą predefiniowanej funkcji, więc całkiem możliwe jest użycie go jako nazwy zmiennej we własnym kodzie. Chociaż prawdą jest, że generalnie należy unikać takich kolizji, filejest to szczególny przypadek, ponieważ prawie nigdy nie ma potrzeby korzystania z niego, dlatego często jest uważany za wyjątek od wytycznych. Jeśli nie chcesz tego robić, PEP8 zaleca dołączenie jednego podkreślenia do takich nazw, tzn. To file_, co musisz zgodzić się, jest nadal dość czytelne.
martineau

9
Dzięki Martineau, masz absolutną rację. Za szybko przeskoczyłem do wniosków.
computermacgyver

40
Bardziej pythonicznym sposobem dla # 2 może być plik w [f for f in os.listdir ('/ mydir') if f.endswith ('. Txt')]:
ozgur

247

Użyj glob .

>>> import glob
>>> glob.glob('./*.txt')
['./outline.txt', './pip-log.txt', './test.txt', './testingvim.txt']

Jest to nie tylko łatwe, ale nie uwzględnia także wielkości liter. (Przynajmniej jest tak, jak powinno być w systemie Windows. Nie jestem pewien co do innych systemów operacyjnych.)
Jon Coombs

35
Uważaj, że globnie można rekurencyjnie znaleźć plików, jeśli Twój python ma mniej niż 3.5 więcej informować
Qun

najlepsze jest to, że możesz użyć testu wyrażeń regularnych * .txt
Alex Punnen

@JonCoombs nie. Przynajmniej nie w systemie Linux.
Karuhanga,

157

Coś takiego powinno wystarczyć

for root, dirs, files in os.walk(directory):
    for file in files:
        if file.endswith('.txt'):
            print file

73
+1 za nazywanie zmiennych root, dirs, fileszamiast r, d, f. O wiele bardziej czytelny.
Clément

27
Zauważ, że rozróżniana jest wielkość liter (nie będzie pasować do .TXT lub .Txt), więc prawdopodobnie będziesz chciał to zrobić, jeśli file.lower (). Kończy się na ('. Txt'):
Jon Coombs

1
twoja odpowiedź dotyczy podkatalogu.
Sam Liao,

117

Coś takiego będzie działać:

>>> import os
>>> path = '/usr/share/cups/charmaps'
>>> text_files = [f for f in os.listdir(path) if f.endswith('.txt')]
>>> text_files
['euc-cn.txt', 'euc-jp.txt', 'euc-kr.txt', 'euc-tw.txt', ... 'windows-950.txt']

Jak zapisać ścieżkę do plików tekstowych? ['path / euc-cn.txt', ... 'path / windows-950.txt']
IceQueeny,

5
Możesz użyć os.path.joinna każdym elemencie text_files. To może być coś takiego text_files = [os.path.join(path, f) for f in os.listdir(path) if f.endswith('.txt')].
Seth

54

Możesz po prostu użyć pathlibs 1 :glob

import pathlib

list(pathlib.Path('your_directory').glob('*.txt'))

lub w pętli:

for txt_file in pathlib.Path('your_directory').glob('*.txt'):
    # do something with "txt_file"

Jeśli chcesz to rekurencyjne, możesz użyć .glob('**/*.txt)


1pathlib moduł został w standardowym biblioteki w pytona 3.4. Ale możesz zainstalować tylne porty tego modułu nawet na starszych wersjach Pythona (tj. Używając condalub pip): pathlibi pathlib2.


**/*.txtnie jest obsługiwany przez starsze wersje Pythona. Rozwiązałem to dzięki: foundfiles= subprocess.check_output("ls **/*.txt", shell=True) for foundfile in foundfiles.splitlines(): print foundfile
Romanowi

1
@Roman Tak, to była tylko prezentacja tego, co pathlibmożna zrobić, a ja już uwzględniłem wymagania dotyczące wersji Pythona. :) Ale jeśli twoje podejście nie zostało jeszcze opublikowane, dlaczego nie dodać go jako kolejnej odpowiedzi?
MSeifert

1
tak, opublikowanie odpowiedzi dałoby mi zdecydowanie lepsze możliwości formatowania. Umieszczam to tam, ponieważ uważam, że jest to bardziej odpowiednie miejsce.
Roman

5
Pamiętaj, że możesz także użyć, rglobjeśli chcesz szukać przedmiotów rekurencyjnie. Np..rglob('*.txt')
Bram Vanroy

40
import os

path = 'mypath/path' 
files = os.listdir(path)

files_txt = [i for i in files if i.endswith('.txt')]

29

Lubię os.walk () :

import os

for root, dirs, files in os.walk(dir):
    for f in files:
        if os.path.splitext(f)[1] == '.txt':
            fullpath = os.path.join(root, f)
            print(fullpath)

Lub z generatorami:

import os

fileiter = (os.path.join(root, f)
    for root, _, files in os.walk(dir)
    for f in files)
txtfileiter = (f for f in fileiter if os.path.splitext(f)[1] == '.txt')
for txt in txtfileiter:
    print(txt)

28

Oto kolejne wersje tego samego, które dają nieco inne wyniki:

glob.iglob ()

import glob
for f in glob.iglob("/mydir/*/*.txt"): # generator, search immediate subdirectories 
    print f

glob.glob1 ()

print glob.glob1("/mydir", "*.tx?")  # literal_directory, basename_pattern

fnmatch.filter ()

import fnmatch, os
print fnmatch.filter(os.listdir("/mydir"), "*.tx?") # include dot-files

3
Dla ciekawskich glob1()jest funkcja pomocnicza w globmodule, która nie jest wymieniona w dokumentacji Pythona. Istnieje kilka wbudowanych komentarzy opisujących, co robi w pliku źródłowym, patrz .../Lib/glob.py.
martineau,

1
@martineau: glob.glob1()nie jest publiczny, ale jest dostępny w Pythonie 2.4-2.7; 3.0-3.2; pypy; jython github.com/zed/test_glob1
jfs

1
Dzięki, to dobra dodatkowa informacja do podjęcia przy podejmowaniu decyzji, czy użyć nieudokumentowanej funkcji prywatnej w module. ;-) Oto trochę więcej. Wersja Python 2.7 ma tylko 12 linii i wygląda na to, że można ją łatwo wyodrębnić z globmodułu.
martineau,

21

path.py to kolejna alternatywa: https://github.com/jaraco/path.py

from path import path
p = path('/path/to/the/directory')
for f in p.files(pattern='*.txt'):
    print f

Fajnie, akceptuje również wyrażenie regularne we wzorcu. Używam for f in p.walk(pattern='*.txt')przejść przez wszystkie podfoldery
Kostanos,

1
Jest też pathlib. Możesz zrobić coś takiego: list(p.glob('**/*.py'))
user2233949,

15

Python v3.5 +

Szybka metoda z użyciem os.scandir w funkcji rekurencyjnej. Wyszukuje wszystkie pliki z określonym rozszerzeniem w folderze i podfolderach.

import os

def findFilesInFolder(path, pathList, extension, subFolders = True):
    """  Recursive function to find all files of an extension type in a folder (and optionally in all subfolders too)

    path:        Base directory to find files
    pathList:    A list that stores all paths
    extension:   File extension to find
    subFolders:  Bool.  If True, find files in all subfolders under path. If False, only searches files in the specified folder
    """

    try:   # Trapping a OSError:  File permissions problem I believe
        for entry in os.scandir(path):
            if entry.is_file() and entry.path.endswith(extension):
                pathList.append(entry.path)
            elif entry.is_dir() and subFolders:   # if its a directory, then repeat process as a nested function
                pathList = findFilesInFolder(entry.path, pathList, extension, subFolders)
    except OSError:
        print('Cannot access ' + path +'. Probably a permissions error')

    return pathList

dir_name = r'J:\myDirectory'
extension = ".txt"

pathList = []
pathList = findFilesInFolder(dir_name, pathList, extension, True)

Aktualizacja kwietnia 2019 r

Jeśli przeszukujesz katalogi zawierające pliki 10 000, dołączanie do listy staje się nieefektywne. „Uzyskanie” wyników jest lepszym rozwiązaniem. Dołączyłem również funkcję konwersji danych wyjściowych na ramkę danych Pandas.

import os
import re
import pandas as pd
import numpy as np


def findFilesInFolderYield(path,  extension, containsTxt='', subFolders = True, excludeText = ''):
    """  Recursive function to find all files of an extension type in a folder (and optionally in all subfolders too)

    path:               Base directory to find files
    extension:          File extension to find.  e.g. 'txt'.  Regular expression. Or  'ls\d' to match ls1, ls2, ls3 etc
    containsTxt:        List of Strings, only finds file if it contains this text.  Ignore if '' (or blank)
    subFolders:         Bool.  If True, find files in all subfolders under path. If False, only searches files in the specified folder
    excludeText:        Text string.  Ignore if ''. Will exclude if text string is in path.
    """
    if type(containsTxt) == str: # if a string and not in a list
        containsTxt = [containsTxt]

    myregexobj = re.compile('\.' + extension + '$')    # Makes sure the file extension is at the end and is preceded by a .

    try:   # Trapping a OSError or FileNotFoundError:  File permissions problem I believe
        for entry in os.scandir(path):
            if entry.is_file() and myregexobj.search(entry.path): # 

                bools = [True for txt in containsTxt if txt in entry.path and (excludeText == '' or excludeText not in entry.path)]

                if len(bools)== len(containsTxt):
                    yield entry.stat().st_size, entry.stat().st_atime_ns, entry.stat().st_mtime_ns, entry.stat().st_ctime_ns, entry.path

            elif entry.is_dir() and subFolders:   # if its a directory, then repeat process as a nested function
                yield from findFilesInFolderYield(entry.path,  extension, containsTxt, subFolders)
    except OSError as ose:
        print('Cannot access ' + path +'. Probably a permissions error ', ose)
    except FileNotFoundError as fnf:
        print(path +' not found ', fnf)

def findFilesInFolderYieldandGetDf(path,  extension, containsTxt, subFolders = True, excludeText = ''):
    """  Converts returned data from findFilesInFolderYield and creates and Pandas Dataframe.
    Recursive function to find all files of an extension type in a folder (and optionally in all subfolders too)

    path:               Base directory to find files
    extension:          File extension to find.  e.g. 'txt'.  Regular expression. Or  'ls\d' to match ls1, ls2, ls3 etc
    containsTxt:        List of Strings, only finds file if it contains this text.  Ignore if '' (or blank)
    subFolders:         Bool.  If True, find files in all subfolders under path. If False, only searches files in the specified folder
    excludeText:        Text string.  Ignore if ''. Will exclude if text string is in path.
    """

    fileSizes, accessTimes, modificationTimes, creationTimes , paths  = zip(*findFilesInFolderYield(path,  extension, containsTxt, subFolders))
    df = pd.DataFrame({
            'FLS_File_Size':fileSizes,
            'FLS_File_Access_Date':accessTimes,
            'FLS_File_Modification_Date':np.array(modificationTimes).astype('timedelta64[ns]'),
            'FLS_File_Creation_Date':creationTimes,
            'FLS_File_PathName':paths,
                  })

    df['FLS_File_Modification_Date'] = pd.to_datetime(df['FLS_File_Modification_Date'],infer_datetime_format=True)
    df['FLS_File_Creation_Date'] = pd.to_datetime(df['FLS_File_Creation_Date'],infer_datetime_format=True)
    df['FLS_File_Access_Date'] = pd.to_datetime(df['FLS_File_Access_Date'],infer_datetime_format=True)

    return df

ext =   'txt'  # regular expression 
containsTxt=[]
path = 'C:\myFolder'
df = findFilesInFolderYieldandGetDf(path,  ext, containsTxt, subFolders = True)

14

Python ma wszystkie narzędzia, aby to zrobić:

import os

the_dir = 'the_dir_that_want_to_search_in'
all_txt_files = filter(lambda x: x.endswith('.txt'), os.listdir(the_dir))

1
Jeśli chcesz all_txt_files się lista:all_txt_files = list(filter(lambda x: x.endswith('.txt'), os.listdir(the_dir)))
Ena

12

Aby wszystkie nazwy plików „.txt” znalazły się w folderze „dataPath” jako listę w języku Python:

from os import listdir
from os.path import isfile, join
path = "/dataPath/"
onlyTxtFiles = [f for f in listdir(path) if isfile(join(path, f)) and  f.endswith(".txt")]
print onlyTxtFiles

12

Wypróbuj to, aby rekursywnie znaleźć wszystkie twoje pliki:

import glob, os
os.chdir("H:\\wallpaper")# use whatever directory you want

#double\\ no single \

for file in glob.glob("**/*.txt", recursive = True):
    print(file)

nie z wersją rekurencyjną (podwójna gwiazda:) **. Dostępne tylko w Pythonie 3. Nie podoba mi się ta chdirczęść. Nie ma takiej potrzeby.
Jean-François Fabre

2
cóż, możesz użyć biblioteki os, aby dołączyć do ścieżki, np., filepath = os.path.join('wallpaper')a następnie użyć jej jako glob.glob(filepath+"**/*.psd", recursive = True), co dałoby ten sam wynik.
Mitalee Rao,

8
import os
import sys 

if len(sys.argv)==2:
    print('no params')
    sys.exit(1)

dir = sys.argv[1]
mask= sys.argv[2]

files = os.listdir(dir); 

res = filter(lambda x: x.endswith(mask), files); 

print res

8

Zrobiłem test (Python 3.6.4, W7x64), aby sprawdzić, które rozwiązanie jest najszybsze dla jednego folderu, bez podkatalogów, aby uzyskać listę pełnych ścieżek plików dla plików o określonym rozszerzeniu.

W skrócie, dla tego zadania os.listdir()jest najszybszym i 1,7x szybciej niż następna najlepsza: os.walk()(! Z przerwą), 2,7X jak najszybciej pathlib, 3.2x szybszy niż os.scandir()i 3.3x szybszy niż glob.
Pamiętaj, że wyniki te zmienią się, gdy będziesz potrzebować wyników rekurencyjnych. Jeśli skopiujesz / wkleisz jedną z poniższych metod, dodaj .lower (), w przeciwnym razie .EXT nie zostanie znaleziony podczas wyszukiwania .ext.

import os
import pathlib
import timeit
import glob

def a():
    path = pathlib.Path().cwd()
    list_sqlite_files = [str(f) for f in path.glob("*.sqlite")]

def b(): 
    path = os.getcwd()
    list_sqlite_files = [f.path for f in os.scandir(path) if os.path.splitext(f)[1] == ".sqlite"]

def c():
    path = os.getcwd()
    list_sqlite_files = [os.path.join(path, f) for f in os.listdir(path) if f.endswith(".sqlite")]

def d():
    path = os.getcwd()
    os.chdir(path)
    list_sqlite_files = [os.path.join(path, f) for f in glob.glob("*.sqlite")]

def e():
    path = os.getcwd()
    list_sqlite_files = [os.path.join(path, f) for f in glob.glob1(str(path), "*.sqlite")]

def f():
    path = os.getcwd()
    list_sqlite_files = []
    for root, dirs, files in os.walk(path):
        for file in files:
            if file.endswith(".sqlite"):
                list_sqlite_files.append( os.path.join(root, file) )
        break



print(timeit.timeit(a, number=1000))
print(timeit.timeit(b, number=1000))
print(timeit.timeit(c, number=1000))
print(timeit.timeit(d, number=1000))
print(timeit.timeit(e, number=1000))
print(timeit.timeit(f, number=1000))

Wyniki:

# Python 3.6.4
0.431
0.515
0.161
0.548
0.537
0.274

Dokumentacja Python 3.6.5 stwierdza: Funkcja os.scandir () zwraca pozycje katalogu wraz z informacjami o atrybutach pliku, zapewniając lepszą wydajność [niż os.listdir ()] w wielu typowych przypadkach użycia.
Bill Oldroyd

Brakuje mi skali skalowania tego testu, ile plików użyłeś w tym teście? jak się porównują, jeśli skalujesz liczbę w górę / w dół?
N4ppeL

5

Ten kod upraszcza moje życie.

import os
fnames = ([file for root, dirs, files in os.walk(dir)
    for file in files
    if file.endswith('.txt') #or file.endswith('.png') or file.endswith('.pdf')
    ])
for fname in fnames: print(fname)


5

Aby uzyskać tablicę nazw plików „.txt” z folderu o nazwie „dane” w tym samym katalogu, zwykle używam tego prostego wiersza kodu:

import os
fileNames = [fileName for fileName in os.listdir("data") if fileName.endswith(".txt")]

3

Sugeruję użycie fnmatch i górnej metody. W ten sposób możesz znaleźć jedno z poniższych:

  1. Imię. txt ;
  2. Imię. TXT ;
  3. Imię. Tekst

.

import fnmatch
import os

    for file in os.listdir("/Users/Johnny/Desktop/MyTXTfolder"):
        if fnmatch.fnmatch(file.upper(), '*.TXT'):
            print(file)

3

Oto jeden z extend()

types = ('*.jpg', '*.png')
images_list = []
for files in types:
    images_list.extend(glob.glob(os.path.join(path, files)))

Nie do użytku z .txt:)
Efreeto

2

Funkcjonalne rozwiązanie z podkatalogami:

from fnmatch import filter
from functools import partial
from itertools import chain
from os import path, walk

print(*chain(*(map(partial(path.join, root), filter(filenames, "*.txt")) for root, _, filenames in walk("mydir"))))

15
Czy ten kod chcesz zachować na dłuższą metę?
Simeon Visser

2

Jeśli folder zawiera wiele plików lub pamięć jest ograniczeniem, rozważ użycie generatorów:

def yield_files_with_extensions(folder_path, file_extension):
   for _, _, files in os.walk(folder_path):
       for file in files:
           if file.endswith(file_extension):
               yield file

Opcja A: Iteracja

for f in yield_files_with_extensions('.', '.txt'): 
    print(f)

Opcja B: zdobądź wszystko

files = [f for f in yield_files_with_extensions('.', '.txt')]

2

Możliwe do skopiowania rozwiązanie podobne do ghostdog:

def get_all_filepaths(root_path, ext):
    """
    Search all files which have a given extension within root_path.

    This ignores the case of the extension and searches subdirectories, too.

    Parameters
    ----------
    root_path : str
    ext : str

    Returns
    -------
    list of str

    Examples
    --------
    >>> get_all_filepaths('/run', '.lock')
    ['/run/unattended-upgrades.lock',
     '/run/mlocate.daily.lock',
     '/run/xtables.lock',
     '/run/mysqld/mysqld.sock.lock',
     '/run/postgresql/.s.PGSQL.5432.lock',
     '/run/network/.ifstate.lock',
     '/run/lock/asound.state.lock']
    """
    import os
    all_files = []
    for root, dirs, files in os.walk(root_path):
        for filename in files:
            if filename.lower().endswith(ext):
                all_files.append(os.path.join(root, filename))
    return all_files

1

użyj modułu Python OS , aby znaleźć pliki z określonym rozszerzeniem.

prosty przykład jest tutaj:

import os

# This is the path where you want to search
path = r'd:'  

# this is extension you want to detect
extension = '.txt'   # this can be : .jpg  .png  .xls  .log .....

for root, dirs_list, files_list in os.walk(path):
    for file_name in files_list:
        if os.path.splitext(file_name)[-1] == extension:
            file_name_path = os.path.join(root, file_name)
            print file_name
            print file_name_path   # This is the full path of the filter file

0

Wielu użytkowników odpowiedziało os.walkodpowiedziami, które obejmują wszystkie pliki, ale także wszystkie katalogi i podkatalogi oraz ich pliki.

import os


def files_in_dir(path, extension=''):
    """
       Generator: yields all of the files in <path> ending with
       <extension>

       \param   path       Absolute or relative path to inspect,
       \param   extension  [optional] Only yield files matching this,

       \yield              [filenames]
    """


    for _, dirs, files in os.walk(path):
        dirs[:] = []  # do not recurse directories.
        yield from [f for f in files if f.endswith(extension)]

# Example: print all the .py files in './python'
for filename in files_in_dir('./python', '*.py'):
    print("-", filename)

Lub dla jednego, w którym nie potrzebujesz generatora:

path, ext = "./python", ext = ".py"
for _, _, dirfiles in os.walk(path):
    matches = (f for f in dirfiles if f.endswith(ext))
    break

for filename in matches:
    print("-", filename)

Jeśli zamierzasz używać dopasowań do czegoś innego, możesz chcieć, aby była to lista zamiast wyrażenia generatora:

    matches = [f for f in dirfiles if f.endswith(ext)]

0

Prosta metoda za pomocą forpętli:

import os

dir = ["e","x","e"]

p = os.listdir('E:')  #path

for n in range(len(p)):
   name = p[n]
   myfile = [name[-3],name[-2],name[-1]]  #for .txt
   if myfile == dir :
      print(name)
   else:
      print("nops")

Chociaż można to bardziej uogólnić.


bardzo niepythonic sposób sprawdzania rozszerzenia. Niebezpieczne też. Co jeśli nazwa jest za krótka? i po co używać listy znaków, a nie ciągów?
Jean-François Fabre
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.