Temukan semua file dalam direktori dengan ekstensi .txt dalam Python


1043

Bagaimana saya bisa menemukan semua file dalam direktori yang memiliki ekstensi .txtdalam python?

Jawaban:


2358

Anda bisa menggunakan glob:

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

atau hanya os.listdir:

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

atau jika Anda ingin melintasi direktori, gunakan 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
Menggunakan solusi # 2, Bagaimana Anda membuat file atau daftar dengan info itu?
Merlin

72
@ ghostdog74: Menurut pendapat saya akan lebih tepat untuk menulis for file in fdaripada karena for files in fkarena apa yang ada dalam variabel adalah nama file tunggal. Yang lebih baik adalah mengubah fto filesdan kemudian for for loop menjadi for file in files.
martineau

45
@computermacgyver: Tidak, filebukan kata yang dilindungi undang-undang, hanya nama fungsi yang telah ditentukan, jadi sangat mungkin untuk menggunakannya sebagai nama variabel dalam kode Anda sendiri. Meskipun memang benar bahwa secara umum seseorang harus menghindari tabrakan seperti itu, fileadalah kasus khusus karena hampir tidak pernah ada kebutuhan untuk menggunakannya, sehingga sering dianggap pengecualian terhadap pedoman. Jika Anda tidak ingin melakukan itu, PEP8 merekomendasikan menambahkan satu garis bawah untuk nama-nama tersebut, yaitu file_, yang harus Anda setujui masih dapat dibaca.
martineau

9
Terima kasih, Martineau, Anda memang benar. Saya melompat terlalu cepat ke kesimpulan.
computermacgyver

40
Cara yang lebih Pythonic untuk # 2 dapat untuk file dalam [f untuk f di os.listdir ('/ mydir') jika f.endswith ('. Txt')]:
ozgur

247

Gunakan glob .

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

Tidak hanya semudah ini, tetapi juga case-sensitive. (Setidaknya, itu pada Windows, sebagaimana mestinya. Saya tidak yakin tentang OS lain.)
Jon Coombs

35
Waspadalah yang globtidak dapat menemukan file secara rekursif jika python Anda di bawah 3.5. informasi lebih lanjut
qun

bagian terbaiknya adalah Anda dapat menggunakan tes ekspresi reguler * .txt
Alex Punnen

@JonCoombs tidak Paling tidak di Linux.
Karuhanga

157

Sesuatu seperti itu harus melakukan pekerjaannya

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

73
+1 untuk penamaan variabel Anda, root, dirs, filesbukan r, d, f. Jauh lebih mudah dibaca.
Clément

27
Perhatikan bahwa ini peka huruf besar kecil (tidak akan cocok dengan .TXT atau .Txt), jadi Anda mungkin ingin melakukannya jika file.lower (). Endswith ('. Txt'):
Jon Coombs

1
jawaban Anda berkaitan dengan subdirektori.
Sam Liao

117

Sesuatu seperti ini akan bekerja:

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

Bagaimana cara saya menyimpan jalur ke text_files? [ 'path / EUC-cn.txt', ... 'path / windows-950.txt']
IceQueeny

5
Anda dapat menggunakan os.path.joinpada setiap elemen text_files. Bisa jadi sesuatu seperti text_files = [os.path.join(path, f) for f in os.listdir(path) if f.endswith('.txt')].
Seth

55

Anda cukup menggunakan pathlibs 1 :glob

import pathlib

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

atau dalam satu lingkaran:

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

Jika Anda menginginkannya bersifat rekursif, Anda dapat menggunakannya .glob('**/*.txt)


1 The pathlibModul termasuk dalam perpustakaan standar di python 3.4. Tetapi Anda dapat menginstal port-kembali modul itu bahkan pada versi Python yang lebih lama (yaitu menggunakan condaatau pip): pathlibdan pathlib2.


**/*.txttidak didukung oleh versi python yang lebih lama. Jadi saya memecahkan masalah ini dengan: foundfiles= subprocess.check_output("ls **/*.txt", shell=True) for foundfile in foundfiles.splitlines(): print foundfile
Roman

1
@ Roman Ya, itu hanya showcase apa yang pathlibbisa dilakukan dan saya sudah memasukkan persyaratan versi Python. :) Tetapi jika pendekatan Anda belum diposting mengapa tidak menambahkannya sebagai jawaban lain?
MSeifert

1
ya, memposting jawaban akan memberi saya kemungkinan memformat yang lebih baik, pasti. Saya mempostingnya di sana karena saya pikir ini adalah tempat yang lebih tepat untuk itu.
Roman

5
Perhatikan bahwa Anda juga dapat menggunakan rglobjika Anda ingin mencari item secara rekursif. Misalnya.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

Saya suka 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)

Atau dengan generator:

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

Berikut ini lebih banyak versi yang sama yang menghasilkan hasil yang sedikit berbeda:

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
Bagi yang penasaran, glob1()adalah fungsi pembantu dalam globmodul yang tidak tercantum dalam dokumentasi Python. Ada beberapa komentar inline yang menjelaskan apa yang dilakukannya di file sumber, lihat .../Lib/glob.py.
martineau

1
@martineau: glob.glob1()tidak umum tetapi tersedia di Python 2.4-2.7; 3.0-3.2; pypy; jython github.com/zed/test_glob1
jfs

1
Terima kasih, itu informasi tambahan yang baik untuk dimiliki ketika memutuskan apakah akan menggunakan fungsi pribadi tidak berdokumen dalam modul. ;-) Ini sedikit lagi. Versi Python 2.7 hanya sepanjang 12 baris dan sepertinya bisa dengan mudah diekstraksi dari globmodul.
martineau

21

path.py adalah alternatif lain: 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

Keren, itu juga menerima ekspresi reguler dalam pola. Saya menggunakan for f in p.walk(pattern='*.txt')melalui setiap subfolder
Kostanos

1
Ya ada juga pathlib. Anda dapat melakukan sesuatu seperti: list(p.glob('**/*.py'))
user2233949

15

Python v3.5 +

Metode cepat menggunakan os.scandir dalam fungsi rekursif. Mencari semua file dengan ekstensi yang ditentukan dalam folder dan sub-folder.

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)

Perbarui April 2019

Jika Anda mencari di direktori yang berisi 10.000 file, menambahkan ke daftar menjadi tidak efisien. 'Menghasilkan' hasilnya adalah solusi yang lebih baik. Saya juga menyertakan fungsi untuk mengkonversi output ke Pandframe Dataframe.

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 memiliki semua alat untuk melakukan ini:

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
Jika Anda ingin all_txt_files menjadi daftar:all_txt_files = list(filter(lambda x: x.endswith('.txt'), os.listdir(the_dir)))
Ena

12

Untuk mendapatkan semua nama file '.txt' di dalam folder 'dataPath' sebagai daftar dengan cara Pythonic:

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

Coba ini, ini akan menemukan semua file Anda secara rekursif:

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)

tidak dengan versi rekursif (bintang ganda:) **. Hanya tersedia dalam python 3. Yang tidak saya sukai adalah chdirbagiannya. Tidak perlu untuk itu.
Jean-François Fabre

2
baik, Anda bisa menggunakan pustaka os untuk bergabung dengan path, misalnya, filepath = os.path.join('wallpaper')dan kemudian menggunakannya sebagai glob.glob(filepath+"**/*.psd", recursive = True), yang akan menghasilkan hasil yang sama.
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

Saya melakukan tes (Python 3.6.4, W7x64) untuk melihat solusi mana yang tercepat untuk satu folder, tanpa subdirektori, untuk mendapatkan daftar path file lengkap untuk file dengan ekstensi spesifik.

Singkatnya, untuk tugas ini os.listdir()adalah yang tercepat dan 1,7x lebih cepat dari yang terbaik berikutnya: os.walk()(dengan istirahat!), 2,7x secepat pathlib, 3,2x lebih cepat dari os.scandir()dan 3,3x lebih cepat daripada glob.
Harap diingat, bahwa hasil itu akan berubah ketika Anda membutuhkan hasil rekursif. Jika Anda menyalin / menempel satu metode di bawah ini, harap tambahkan .lower () jika tidak .EXT tidak akan ditemukan saat mencari .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))

Hasil:

# Python 3.6.4
0.431
0.515
0.161
0.548
0.537
0.274

Dokumentasi Python 3.6.5 menyatakan: Fungsi os.scandir () mengembalikan entri direktori bersama dengan informasi atribut file, memberikan kinerja yang lebih baik [daripada os.listdir ()] untuk banyak kasus penggunaan umum.
Bill Oldroyd

Saya tidak mengetahui skala skala pengujian ini, berapa banyak file yang Anda gunakan dalam tes ini? bagaimana mereka membandingkan jika Anda menaikkan / menurunkan angka?
N4ppeL

5

Kode ini membuat hidup saya lebih sederhana.

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

Untuk mendapatkan larik nama file ".txt" dari folder bernama "data" di direktori yang sama, saya biasanya menggunakan baris kode sederhana ini:

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

3

Saya menyarankan Anda untuk menggunakan fnmatch dan metode atas. Dengan cara ini Anda dapat menemukan salah satu dari yang berikut:

  1. Nama. txt ;
  2. Nama. TXT ;
  3. Nama. Txt

.

import fnmatch
import os

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

3

Ini satu dengan extend()

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

Tidak untuk digunakan dengan .txt:)
Efreeto

2

Solusi fungsional dengan sub-direktori:

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
Apakah kode ini ingin Anda pertahankan dalam jangka panjang?
Simeon Visser

2

Jika folder tersebut berisi banyak file atau memori merupakan kendala, pertimbangkan untuk menggunakan generator:

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

Opsi A: Iterate

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

Opsi B: Dapatkan semua

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

2

Solusi copy-pastable mirip dengan 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

gunakan modul Python OS untuk menemukan file dengan ekstensi spesifik.

contoh sederhana ada di sini:

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

Banyak pengguna menjawab dengan os.walkjawaban, yang mencakup semua file tetapi juga semua direktori dan subdirektori dan file mereka.

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)

Atau untuk yang tidak memerlukan generator:

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)

Jika Anda akan menggunakan kecocokan untuk sesuatu yang lain, Anda mungkin ingin menjadikannya daftar daripada ekspresi generator:

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

0

Metode sederhana dengan menggunakan forloop:

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

Padahal ini bisa dibuat lebih umum.


cara yang sangat unpythonic memeriksa ekstensi. Tidak aman juga. Bagaimana jika namanya terlalu pendek? dan mengapa menggunakan daftar karakter dan bukan string?
Jean-François Fabre
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.