Câu hỏi Làm cách nào để liệt kê tất cả các tệp của một thư mục?


Làm thế nào tôi có thể liệt kê tất cả các tập tin của một thư mục trong Python và thêm chúng vào một list?


2825
2017-07-08 19:31


gốc


Có quan hệ với Cách lấy danh sách các thư mục con - rds
os.listdir(path) trả về một danh sách các chuỗi tên tập tin và thư mục con từ đường dẫn đã cho, hoặc hiện tại nếu bỏ qua. (Đặt điều này ở đây để mọi người từ Google xem vì câu trả lời hàng đầu hiện tại không trả lời được câu hỏi.) - Apollys
Tất cả các tệp chỉ? Bạn có muốn liệt kê các thư mục con không? - Aleksandar Jovanovic
Điều này hoạt động độc đáo (câu trả lời hàng đầu bên dưới): from os import listdir  from os.path import isfile, join  files = [f for f in listdir(mypath) if isfile(join(mypath, f))] Lưu ý: bạn cần gán một chuỗi vào đường dẫn thư mục nơi các tệp được lưu trữ (ví dụ: mypath = "users/name/desktop/"). - Arshin
Bạn có nghĩa là các tệp như: Các tệp thông thường không phải là thư mục con hoặc liên kết hoặc tất cả các tệp, bao gồm các thư mục con và liên kết? - Mulliganaceous


Các câu trả lời:


os.listdir() sẽ giúp bạn có được mọi thứ trong thư mục - tệp và thư mục.

Nếu bạn muốn chỉ tệp, bạn có thể lọc xuống bằng cách sử dụng os.path:

from os import listdir
from os.path import isfile, join
onlyfiles = [f for f in listdir(mypath) if isfile(join(mypath, f))]

hoặc bạn có thể sử dụng os.walk() sẽ tạo ra hai danh sách cho mỗi thư mục mà nó truy cập - tách thành các tệp và thư mục cho bạn. Nếu bạn chỉ muốn thư mục trên cùng bạn có thể phá vỡ lần đầu tiên nó mang lại

from os import walk

f = []
for (dirpath, dirnames, filenames) in walk(mypath):
    f.extend(filenames)
    break

Và cuối cùng, như ví dụ đó cho thấy, thêm một danh sách vào danh sách khác, bạn có thể sử dụng .extend() hoặc là

>>> q = [1, 2, 3]
>>> w = [4, 5, 6]
>>> q = q + w
>>> q
[1, 2, 3, 4, 5, 6]

Cá nhân tôi thích .extend()


2829
2017-07-08 21:01



Dường như không hoạt động trên Windows với tên tệp unicode vì một số lý do. - cdiggins
Một chút đơn giản hơn: (_, _, filenames) = walk(mypath).next()  (nếu bạn tự tin rằng chuyến đi bộ sẽ trả lại ít nhất một giá trị, mà nó nên.) - misterbee
Sửa đổi nhẹ để lưu trữ đường dẫn đầy đủ: cho (dirpath, dirnames, tên tệp) trong os.walk (mypath): checksum_files.extend (os.path.join (dirpath, filename) cho tên tệp trong tên tệp) ngắt - okigan
f.extend(filenames) không thực sự tương đương với f = f + filenames. extend sẽ sửa đổi f tại chỗ, trong khi việc thêm tạo danh sách mới ở vị trí bộ nhớ mới. Điều này có nghĩa là extend nói chung hiệu quả hơn +, nhưng đôi khi có thể dẫn đến nhầm lẫn nếu nhiều đối tượng chứa tham chiếu đến danh sách. Cuối cùng, đáng chú ý là f += filenames tương đương với f.extend(filenames), không phải  f = f + filenames. - Benjamin Hodgson♦
@ misterbee, giải pháp của bạn là tốt nhất, chỉ cần một cải tiến nhỏ: _, _, filenames = next(walk(mypath), (None, None, [])) - bgusach


Tôi thích sử dụng glob mô-đun, vì nó khớp với mẫu và mở rộng.

import glob
print(glob.glob("/home/adam/*.txt"))

Nó sẽ trả về một danh sách với các tệp được truy vấn:

['/home/adam/file1.txt', '/home/adam/file2.txt', .... ]

1143
2017-07-09 18:13



đó là một phím tắt cho listdir + fnmatch docs.python.org/library/fnmatch.html#fnmatch.fnmatch - Stefano
Đối với tôi, nó không thêm vào sự mâu thuẫn mà tôi cho nó ăn. Các dấu gạch chéo chính xác tại kết quả đầu vào đúng với dấu gạch chéo ở đầu ra. - Antony Hatchkins
Tôi nghĩ rằng đây sẽ là câu trả lời được chấp nhận vì nó là việc thực hiện đơn giản nhất. - isosceleswheel
Cẩn thận rằng điều này trả về đường dẫn đầy đủ. - xji
để làm rõ, điều này không không phải trả lại "đường dẫn đầy đủ"; nó đơn giản trả về sự mở rộng của glob, bất kể nó có thể là gì. Ví dụ: được cung cấp /home/user/foo/bar/hello.txt, sau đó, nếu chạy trong thư mục foo, các glob("bar/*.txt") sẽ trở lại bar/hello.txt. Có những trường hợp bạn thực sự muốn con đường đầy đủ (tức là tuyệt đối); cho những trường hợp đó, hãy xem stackoverflow.com/questions/51520/… - michael


import os
os.listdir("somedirectory")

sẽ trả về một danh sách tất cả các tệp và thư mục trong "somedirectory".


520
2017-07-08 19:35



Điều này trả về đường dẫn tương đối của các tệp, so với đường dẫn đầy đủ được trả về bởi glob.glob - xji
@JIXiang: os.listdir() luôn luôn trả về tên tệp duy nhất (không phải đường dẫn tương đối). Gì glob.glob() trả về được định hướng bởi định dạng đường dẫn của mẫu đầu vào. - mklement0
os.listdir () -> Nó luôn liệt kê danh sách và tệp bên trong vị trí được cung cấp. Có cách nào để liệt kê chỉ thư mục không phải tập tin? - RishuA


Lấy danh sách các tệp bằng Python 2 và 3


Tôi cũng đã tạo một đoạn video ngắn tại đây:  Python: cách lấy danh sách tệp trong thư mục


os.listdir ()

hoặc ..... nóng để nhận tất cả các tệp (và thư mục) trong thư mục hiện tại (Python 3)

Cách đơn giản nhất để có tệp trong thư mục hiện tại trong Python 3 là điều này. Nó thực sự đơn giản; sử dụng os module và hàm listdir () và bạn sẽ có tệp trong thư mục đó (và các thư mục cuối cùng nằm trong thư mục, nhưng bạn sẽ không có tệp trong thư mục con, để bạn có thể dùng walk - tôi sẽ nói về nó một lát sau).

>>> import os
>>> arr = os.listdir()
>>> arr
['$RECYCLE.BIN', 'work.txt', '3ebooks.txt', 'documents']

Sử dụng glob

Tôi thấy glob dễ dàng hơn để chọn tập tin cùng loại hoặc với một điểm chung. Hãy xem ví dụ sau:

import glob

txtfiles = []
for file in glob.glob("*.txt"):
    txtfiles.append(file)

Sử dụng danh sách hiểu

import glob

mylist = [f for f in glob.glob("*.txt")]

Lấy tên đường dẫn đầy đủ với os.path.abspath

Như bạn thấy, bạn không có đường dẫn đầy đủ của tệp trong mã ở trên. Nếu bạn cần có đường dẫn tuyệt đối, bạn có thể sử dụng chức năng khác của os.path mô-đun gọi là _getfullpathname, đưa tệp bạn nhận được từ os.listdir() như một đối số. Có nhiều cách khác để có đường dẫn đầy đủ, vì chúng tôi sẽ kiểm tra sau (tôi đã thay thế, theo đề xuất của mexmex, _getfullpathname với abspath).

>>> import os
>>> files_path = [os.path.abspath(x) for x in os.listdir()]
>>> files_path
['F:\\documenti\applications.txt', 'F:\\documenti\collections.txt']

Nhận tên đường dẫn đầy đủ của một loại tệp vào tất cả các thư mục con bằng cách đi bộ

Tôi thấy điều này rất hữu ích trong việc tìm kiếm nhiều thứ trong nhiều thư mục, và nó giúp tôi tìm một tập tin mà tôi không nhớ tên:

import os

# Getting the current work directory (cwd)
thisdir = os.getcwd()

# r=root, d=directories, f = files
for r, d, f in os.walk(thisdir):
    for file in f:
        if ".docx" in file:
            print(os.path.join(r, file))

os.listdir (): lấy các tệp trong thư mục hiện tại (Python 2)

Trong Python 2 bạn, nếu bạn muốn danh sách các tệp trong thư mục hiện tại, bạn phải đặt đối số là '.' hoặc os.getcwd () trong phương thức os.listdir.

>>> import os
>>> arr = os.listdir('.')
>>> arr
['$RECYCLE.BIN', 'work.txt', '3ebooks.txt', 'documents']

Để đi lên trong cây thư mục

>>> # Method 1
>>> x = os.listdir('..')

# Method 2
>>> x= os.listdir('/')

Nhận tệp: os.listdir () trong một thư mục cụ thể (Python 2 và 3)

>>> import os
>>> arr = os.listdir('F:\\python')
>>> arr
['$RECYCLE.BIN', 'work.txt', '3ebooks.txt', 'documents']

Nhận tệp của một thư mục con cụ thể với os.listdir ()

import os

x = os.listdir("./content")

os.walk ('.') - thư mục hiện tại

>>> import os
>>> arr = next(os.walk('.'))[2]
>>> arr
['5bs_Turismo1.pdf', '5bs_Turismo1.pptx', 'esperienza.txt']

glob module - tất cả các tệp

import glob
print(glob.glob("*"))

out:['content', 'start.py']

tiếp theo (os.walk ('.')) và os.path.join ('dir', 'file')

>>> import os
>>> arr = []
>>> for d,r,f in next(os.walk("F:\_python)):
>>>     for file in f:
>>>         arr.append(os.path.join(r,file))
...
>>> for f in arr:
>>>     print(files)

>output

F:\\_python\\dict_class.py
F:\\_python\\programmi.txt

tiếp theo (os.walk ('F: \') - nhận được đường dẫn đầy đủ - danh sách hiểu

>>> [os.path.join(r,file) for r,d,f in next(os.walk("F:\\_python")) for file in f]
['F:\\_python\\dict_class.py', 'F:\\_python\\programmi.txt']

os.walk - nhận đường dẫn đầy đủ - tất cả các tệp trong thư mục con

x = [os.path.join(r,file) for r,d,f in os.walk("F:\\_python") for file in f]

>>>x
['F:\\_python\\dict.py', 'F:\\_python\\progr.txt', 'F:\\_python\\readl.py']

os.listdir () - chỉ nhận các tệp txt

>>> arr_txt = [x for x in os.listdir() if x.endswith(".txt")]
>>> print(arr_txt)
['work.txt', '3ebooks.txt']

glob - chỉ lấy các tệp txt

>>> import glob
>>> x = glob.glob("*.txt")
>>> x
['ale.txt', 'alunni2015.txt', 'assenze.text.txt', 'text2.txt', 'untitled.txt']

Sử dụng glob để có được đường dẫn đầy đủ của các tập tin

Nếu tôi cần đường dẫn tuyệt đối của các tệp:

>>> from path import path
>>> from glob import glob
>>> x = [path(f).abspath() for f in glob("F:\*.txt")]
>>> for f in x:
...  print(f)
...
F:\acquistionline.txt
F:\acquisti_2018.txt
F:\bootstrap_jquery_ecc.txt

Sử dụng khác của glob

Nếu tôi muốn tất cả các tệp trong thư mục:

>>> x = glob.glob("*")

Sử dụng os.path.isfile để tránh các thư mục trong danh sách

import os.path
listOfFiles = [f for f in os.listdir() if os.path.isfile(f)]
print(listOfFiles)

> output

['a simple game.py', 'data.txt', 'decorator.py']

Sử dụng pathlib từ (Python 3.4)

import pathlib

>>> flist = []
>>> for p in pathlib.Path('.').iterdir():
...  if p.is_file():
...   print(p)
...   flist.append(p)
...
error.PNG
exemaker.bat
guiprova.mp3
setup.py
speak_gui2.py
thumb.PNG

Nếu bạn muốn sử dụng danh sách hiểu

>>> flist = [p for p in pathlib.Path('.').iterdir() if p.is_file()]

Nhận tất cả và chỉ các tệp có os.walk

import os
x = [i[2] for i in os.walk('.')]
y=[]
for t in x:
    for f in t:
        y.append(f)

>>> y
['append_to_list.py', 'data.txt', 'data1.txt', 'data2.txt', 'data_180617', 'os_walk.py', 'READ2.py', 'read_data.py', 'somma_defaltdic.py', 'substitute_words.py', 'sum_data.py', 'data.txt', 'data1.txt', 'data_180617']

Chỉ nhận các tệp tiếp theo và đi bộ trong một thư mục

>>> import os
>>> x = next(os.walk('F://python'))[2]
>>> x
['calculator.bat','calculator.py']

Chỉ nhận các thư mục tiếp theo và đi bộ trong một thư mục

>>> import os
>>> next(os.walk('F://python'))[1] # for the current dir use ('.')
['python3','others']

Nhận tất cả tên tiểu thư bằng cách đi bộ

>>> for r,d,f in os.walk("F:\_python"):
...  for dirs in d:
...   print(dirs)
...
.vscode
pyexcel
pyschool.py
subtitles
_metaprogramming
.ipynb_checkpoints

os.scandir () từ Python 3.5 trên

>>> import os
>>> x = [f.name for f in os.scandir() if f.is_file()]
>>> x
['calculator.bat','calculator.py']

# Another example with scandir (a little variation from docs.python.org)
# This one is more efficient than os.listdir.
# In this case, it shows the files only in the current directory
# where the script is executed.

>>> import os
>>> with os.scandir() as i:
...  for entry in i:
...   if entry.is_file():
...    print(entry.name)
...
ebookmaker.py
error.PNG
exemaker.bat
guiprova.mp3
setup.py
speakgui4.py
speak_gui2.py
speak_gui3.py
thumb.PNG
>>>

Ví dụ 1: Có bao nhiêu tệp trong thư mục con?

Trong ví dụ này, chúng tôi tìm số lượng tệp được bao gồm trong tất cả thư mục và thư mục con của nó.

import os

def count(dir, counter=0):
    "returns number of files in dir and subdirs"
    for pack in os.walk(dir):
        for f in pack[2]:
            counter += 1
    return dir + " : " + str(counter) + "files"

print(count("F:\\python"))

> output

>'F:\\\python' : 12057 files'

Ex.2: Làm thế nào để sao chép tất cả các tập tin từ một thư mục khác?

Một tập lệnh để đặt hàng trong máy tính của bạn tìm tất cả các tệp thuộc loại (mặc định: pptx) và sao chép chúng trong một thư mục mới.

import os
import shutil
from path import path

destination = "F:\\file_copied"
# os.makedirs(destination)

def copyfile(dir, filetype='pptx', counter=0):
    "Searches for pptx (or other - pptx is the default) files and copies them"
    for pack in os.walk(dir):
        for f in pack[2]:
            if f.endswith(filetype):
                fullpath = pack[0] + "\\" + f
                print(fullpath)
                shutil.copy(fullpath, destination)
                counter += 1
    if counter > 0:
        print("------------------------")
        print("\t==> Found in: `" + dir + "` : " + str(counter) + " files\n")

for dir in os.listdir():
    "searches for folders that starts with `_`"
    if dir[0] == '_':
        # copyfile(dir, filetype='pdf')
        copyfile(dir, filetype='txt')


> Output

_compiti18\Compito Contabilità 1\conti.txt
_compiti18\Compito Contabilità 1\modula4.txt
_compiti18\Compito Contabilità 1\moduloa4.txt
------------------------
==> Found in: `_compiti18` : 3 files

Ví dụ 3: Cách lấy tất cả các tệp trong một tệp txt

Trong trường hợp bạn muốn tạo một tệp txt với tất cả các tên tệp:

import os
mylist = ""
with open("filelist.txt", "w", encoding="utf-8") as file:
    for eachfile in os.listdir():
        mylist += eachfile + "\n"
    file.write(mylist)

333
2018-01-03 15:36



Bạn nên bao gồm đối số đường dẫn đến listdir. - Alejandro Sazo
Nó chắc chắn được khuyến khích để bao gồm một số bối cảnh / giải thích cho mã như là làm cho câu trả lời hữu ích hơn. - EJoshuaS
Tôi đồng ý, nhưng tôi đã không nhận thấy một cái gì đó cũng có, mà python2 đòi hỏi các đối số trong khi python3 là tùy chọn, Nếu bạn cải thiện câu trả lời cho cả hai phiên bản python sẽ là tuyệt vời :) - Alejandro Sazo
Ok, tôi đã đi vào Python 2 và tìm thấy sự khác biệt và tôi đã chỉnh sửa bài đăng. - Giovanni Gianni
Không có lý do gì để làm [f for f in os.listdir()]; os.listdir() đã trả về một list, vì vậy đó chỉ là không cần sao chép bản gốc list trước khi ném nó đi. - ShadowRanger


Một giải pháp một dòng để có được chỉ danh sách tệp (không có thư mục con):

filenames = next(os.walk(path))[2]

hoặc tên đường dẫn tuyệt đối:

paths = [os.path.join(path,fn) for fn in next(os.walk(path))[2]]

144
2018-01-18 17:42



Chỉ một lớp lót nếu bạn đã import os. Dường như ngắn gọn hơn glob() với tôi. - ArtOfWarfare
vấn đề với glob là một thư mục có tên 'something.something' sẽ được trả về bởi glob ('/ home / adam /*.*') - Remi
Trên OS X, có một thứ gọi là gói. Đó là một thư mục thường được coi là một tệp (như atar). Bạn có muốn những người được coi là một tệp hoặc một thư mục không? Sử dụng glob() sẽ coi nó như một tập tin. Phương pháp của bạn sẽ coi nó là một thư mục. - ArtOfWarfare


Lấy các đường dẫn tệp đầy đủ từ một thư mục và tất cả các thư mục con của nó

import os

def get_filepaths(directory):
    """
    This function will generate the file names in a directory 
    tree by walking the tree either top-down or bottom-up. For each 
    directory in the tree rooted at directory top (including top itself), 
    it yields a 3-tuple (dirpath, dirnames, filenames).
    """
    file_paths = []  # List which will store all of the full filepaths.

    # Walk the tree.
    for root, directories, files in os.walk(directory):
        for filename in files:
            # Join the two strings in order to form the full filepath.
            filepath = os.path.join(root, filename)
            file_paths.append(filepath)  # Add it to the list.

    return file_paths  # Self-explanatory.

# Run the above function and store its results in a variable.   
full_file_paths = get_filepaths("/Users/johnny/Desktop/TEST")

  • Đường dẫn tôi đã cung cấp trong hàm trên chứa 3 tệp - hai tệp trong thư mục gốc và một tệp khác trong thư mục con được gọi là "SUBFOLDER". Bây giờ bạn có thể làm những việc như:
  • print full_file_paths sẽ in danh sách:

    • ['/Users/johnny/Desktop/TEST/file1.txt', '/Users/johnny/Desktop/TEST/file2.txt', '/Users/johnny/Desktop/TEST/SUBFOLDER/file3.dat']

Nếu muốn, bạn có thể mở và đọc nội dung hoặc chỉ tập trung vào các tệp có đuôi ".dat" như trong mã bên dưới:

for f in full_file_paths:
  if f.endswith(".dat"):
    print f

/Users/johnny/Desktop/TEST/SUBFOLDER/file3.dat


110
2017-10-11 00:55





Kể từ phiên bản 3.4 đã được xây dựng vòng lặp cho điều này hiệu quả hơn rất nhiều os.listdir():

pathlib: Tính năng mới trong phiên bản 3.4.

>>> import pathlib
>>> [p for p in pathlib.Path('.').iterdir() if p.is_file()]

Theo PEP 428, mục tiêu của pathlib thư viện là cung cấp một hệ thống phân cấp đơn giản của các lớp để xử lý các đường dẫn hệ thống tập tin và các hoạt động phổ biến mà người dùng thực hiện trên chúng.

os.scandir(): Tính năng mới trong phiên bản 3.5.

>>> import os
>>> [entry for entry in os.scandir('.') if entry.is_file()]

Lưu ý rằng os.walk() sử dụng os.scandir() thay vì os.listdir() từ phiên bản 3.5, và tốc độ của nó đã tăng 2-20 lần theo PEP 471.

Hãy để tôi cũng khuyên bạn nên đọc bình luận của ShadowRanger dưới đây.


57
2018-06-18 20:58



Cảm ơn! Tôi nghĩ rằng đó là giải pháp duy nhất không quay trở lại trực tiếp list. Có thể dùng p.name thay vì đầu tiên p cách khác nếu được ưu tiên. - JeromeJ
Chào mừng bạn! Tôi muốn tạo ra pathlib.Path() các trường hợp vì chúng có nhiều phương pháp hữu ích, tôi sẽ không muốn lãng phí chất thải. Bạn cũng có thể gọi str(p) trên chúng cho tên đường dẫn. - SzieberthAdam
Lưu ý: The os.scandir giải pháp sẽ hiệu quả hơn os.listdir với một os.path.is_file kiểm tra hoặc tương tự, ngay cả khi bạn cần list (vì vậy bạn không được hưởng lợi từ lặp lại lười biếng), bởi vì os.scandir sử dụng API do OS cung cấp cung cấp cho bạn is_file thông tin miễn phí khi nó lặp lại, không có chuyến đi vòng quanh tệp tới đĩa stat họ ở tất cả (trên Windows, DirEntrys giúp bạn hoàn thành stat thông tin miễn phí, trên hệ thống * NIX cần thiết stat để biết thêm thông tin is_file, is_dir, v.v., nhưng DirEntry lưu trữ trên đầu tiên stat cho thuận tiện). - ShadowRanger
Tôi đã tìm thấy đây là giải pháp hữu ích nhất (sử dụng pathlib). Tôi có thể dễ dàng nhận được các loại mở rộng cụ thể và đường dẫn tuyệt đối. Cảm ơn bạn! - HEADLESS_0NE
Bạn cũng có thể dùng entry.name chỉ lấy tên tệp hoặc entry.path để có được con đường đầy đủ của nó. Không còn os.path.join () ở khắp nơi. - user136036


tôi thật sự thích câu trả lời của adamk, cho thấy bạn sử dụng glob(), từ mô-đun cùng tên. Điều này cho phép bạn có mẫu phù hợp với *S.

Nhưng như những người khác đã chỉ ra trong các ý kiến, glob() có thể bị vấp ngã trên các dấu gạch chéo không nhất quán. Để giúp điều đó, tôi khuyên bạn nên sử dụng join() và expanduser() chức năng trong os.path mô-đun và có lẽ getcwd() chức năng trong os cũng như mô-đun.

Ví dụ:

from glob import glob

# Return everything under C:\Users\admin that contains a folder called wlp.
glob('C:\Users\admin\*\wlp')

Ở trên là khủng khiếp - con đường đã được hardcoded và sẽ chỉ bao giờ làm việc trên Windows giữa tên ổ đĩa và \s được hardcoded vào đường dẫn.

from glob    import glob
from os.path import join

# Return everything under Users, admin, that contains a folder called wlp.
glob(join('Users', 'admin', '*', 'wlp'))

Các công trình trên tốt hơn, nhưng nó dựa vào tên thư mục Usersthường được tìm thấy trên Windows và không thường thấy trên các hệ điều hành khác. Nó cũng dựa vào người dùng có tên cụ thể, admin.

from glob    import glob
from os.path import expanduser, join

# Return everything under the user directory that contains a folder called wlp.
glob(join(expanduser('~'), '*', 'wlp'))

Điều này hoạt động hoàn hảo trên tất cả các nền tảng.

Một ví dụ tuyệt vời khác hoạt động hoàn hảo trên các nền tảng và thực hiện điều gì đó khác biệt một chút:

from glob    import glob
from os      import getcwd
from os.path import join

# Return everything under the current directory that contains a folder called wlp.
glob(join(getcwd(), '*', 'wlp'))

Hy vọng những ví dụ này giúp bạn thấy sức mạnh của một vài hàm bạn có thể tìm thấy trong các mô-đun thư viện Python chuẩn.


45
2017-07-09 11:43



Extra glob fun: bắt đầu bằng Python 3.5, ** hoạt động miễn là bạn đặt recursive = True. Xem tài liệu ở đây: docs.python.org/3.5/library/glob.html#glob.glob - ArtOfWarfare