Làm thế nào tôi có thể tìm thấy tất cả các tệp trong một thư mục có phần mở rộng .txt
trong python?
Làm thế nào tôi có thể tìm thấy tất cả các tệp trong một thư mục có phần mở rộng .txt
trong python?
Câu trả lời:
Bạn có thể sử dụng glob
:
import glob, os
os.chdir("/mydir")
for file in glob.glob("*.txt"):
print(file)
hoặc đơn giản là os.listdir
:
import os
for file in os.listdir("/mydir"):
if file.endswith(".txt"):
print(os.path.join("/mydir", file))
hoặc nếu bạn muốn duyệt qua thư mục, hãy sử dụng 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))
for file in f
hơn là for files in f
vì trong biến là một tên tệp duy nhất. Thậm chí tốt hơn là thay đổi f
thành files
và sau đó các vòng lặp cho có thể trở thành for file in files
.
file
không phải là một từ dành riêng, chỉ là tên của một hàm được xác định trước, vì vậy hoàn toàn có thể sử dụng nó làm tên biến trong mã của riêng bạn. Mặc dù đúng là nói chung người ta nên tránh va chạm như vậy, file
là một trường hợp đặc biệt vì hầu như không cần sử dụng nó, vì vậy nó thường được coi là một ngoại lệ đối với hướng dẫn. Nếu bạn không muốn làm điều đó, PEP8 khuyên bạn nên thêm một dấu gạch dưới vào các tên như vậy, nghĩa là file_
bạn phải đồng ý vẫn có thể đọc được.
Sử dụng toàn cầu .
>>> import glob
>>> glob.glob('./*.txt')
['./outline.txt', './pip-log.txt', './test.txt', './testingvim.txt']
glob
không thể tìm thấy các tệp đệ quy nếu con trăn của bạn dưới 3,5. thêm thông tin
Một cái gì đó như thế sẽ làm công việc
for root, dirs, files in os.walk(directory):
for file in files:
if file.endswith('.txt'):
print file
root, dirs, files
thay vì r, d, f
. Dễ đọc hơn nhiều.
Một cái gì đó như thế này sẽ hoạt động:
>>> 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']
os.path.join
trên từng yếu tố của text_files
. Nó có thể là một cái gì đó như text_files = [os.path.join(path, f) for f in os.listdir(path) if f.endswith('.txt')]
.
Bạn chỉ có thể sử dụng pathlib
s 1 :glob
import pathlib
list(pathlib.Path('your_directory').glob('*.txt'))
hoặc trong một vòng lặp:
for txt_file in pathlib.Path('your_directory').glob('*.txt'):
# do something with "txt_file"
Nếu bạn muốn nó đệ quy bạn có thể sử dụng .glob('**/*.txt)
1 Các pathlib
mô-đun đã được đưa vào thư viện chuẩn trong python 3.4. Nhưng bạn có thể cài đặt các cổng sau của mô-đun đó ngay cả trên các phiên bản Python cũ hơn (tức là sử dụng conda
hoặc pip
): pathlib
và pathlib2
.
**/*.txt
không được hỗ trợ bởi các phiên bản python cũ. Vì vậy, tôi đã giải quyết vấn đề này bằng: foundfiles= subprocess.check_output("ls **/*.txt", shell=True)
for foundfile in foundfiles.splitlines():
print foundfile
pathlib
có thể làm và tôi đã bao gồm các yêu cầu phiên bản Python. :) Nhưng nếu cách tiếp cận của bạn chưa được đăng, tại sao không thêm nó vào câu trả lời khác?
rglob
nếu bạn muốn tìm các mục đệ quy. Ví dụ:.rglob('*.txt')
import os
path = 'mypath/path'
files = os.listdir(path)
files_txt = [i for i in files if i.endswith('.txt')]
Tôi thích 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)
Hoặc với máy phát điện:
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)
Đây là nhiều phiên bản tương tự tạo ra kết quả hơi khác nhau:
import glob
for f in glob.iglob("/mydir/*/*.txt"): # generator, search immediate subdirectories
print f
print glob.glob1("/mydir", "*.tx?") # literal_directory, basename_pattern
import fnmatch, os
print fnmatch.filter(os.listdir("/mydir"), "*.tx?") # include dot-files
glob1()
là một hàm trợ giúp trong glob
mô-đun không được liệt kê trong tài liệu Python. Có một số ý kiến nội tuyến mô tả những gì nó làm trong tệp nguồn, xem .../Lib/glob.py
.
glob.glob1()
không công khai nhưng nó có sẵn trên Python 2.4-2.7; 3.0-3.2; kim tự tháp; jython github.com/ened/test_glob1
glob
mô-đun.
path.py là một lựa chọn khác: 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
for f in p.walk(pattern='*.txt')
đi qua tất cả các thư mục con
list(p.glob('**/*.py'))
Phương pháp nhanh sử dụng os.scandir trong hàm đệ quy. Tìm kiếm tất cả các tệp có phần mở rộng được chỉ định trong thư mục và thư mục con.
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)
Nếu bạn đang tìm kiếm trên các thư mục chứa 10.000 tệp, việc thêm vào danh sách sẽ không hiệu quả. "Mang lại kết quả" là một giải pháp tốt hơn. Tôi cũng đã bao gồm một chức năng để chuyển đổi đầu ra thành Dữ liệu Pandasrame.
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)
Python có tất cả các công cụ để làm điều này:
import os
the_dir = 'the_dir_that_want_to_search_in'
all_txt_files = filter(lambda x: x.endswith('.txt'), os.listdir(the_dir))
all_txt_files = list(filter(lambda x: x.endswith('.txt'), os.listdir(the_dir)))
Hãy thử điều này sẽ tìm thấy tất cả các tệp của bạn đệ quy:
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)
**
:). Chỉ có sẵn trong python 3. Những gì tôi không thích là chdir
một phần. Không cần điều đó.
filepath = os.path.join('wallpaper')
và sau đó sử dụng nó như glob.glob(filepath+"**/*.psd", recursive = True)
sẽ mang lại kết quả tương tự.
Tôi đã thực hiện một thử nghiệm (Python 3.6.4, W7x64) để xem giải pháp nào là nhanh nhất cho một thư mục, không có thư mục con, để có danh sách các đường dẫn tệp hoàn chỉnh cho các tệp có phần mở rộng cụ thể.
Nói ngắn gọn, đối với nhiệm vụ os.listdir()
này là nhanh nhất và nhanh gấp 1,7 lần so với nhiệm vụ tốt nhất tiếp theo: os.walk()
(với thời gian nghỉ!), pathlib
Nhanh gấp 2,7 lần , nhanh hơn os.scandir()
3,2 lần và nhanh hơn 3,3 lần glob
.
Xin lưu ý rằng những kết quả đó sẽ thay đổi khi bạn cần kết quả đệ quy. Nếu bạn sao chép / dán một phương thức bên dưới, vui lòng thêm .lower () nếu không .EXT sẽ không được tìm thấy khi tìm kiếm .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))
Các kết quả:
# Python 3.6.4
0.431
0.515
0.161
0.548
0.537
0.274
Mã này làm cho cuộc sống của tôi đơn giản hơn.
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)
Sử dụng fnmatch: https://docs.python.org/2/l Library / fnmatch.html
import fnmatch
import os
for file in os.listdir('.'):
if fnmatch.fnmatch(file, '*.txt'):
print file
Để có được một mảng tên tệp ".txt" từ một thư mục có tên là "data" trong cùng thư mục, tôi thường sử dụng dòng mã đơn giản này:
import os
fileNames = [fileName for fileName in os.listdir("data") if fileName.endswith(".txt")]
Tôi đề nghị bạn sử dụng fnmatch và phương pháp trên. Theo cách này, bạn có thể tìm thấy bất kỳ điều nào sau đây:
.
import fnmatch
import os
for file in os.listdir("/Users/Johnny/Desktop/MyTXTfolder"):
if fnmatch.fnmatch(file.upper(), '*.TXT'):
print(file)
Giải pháp chức năng với các thư mục con:
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"))))
Trong trường hợp thư mục chứa nhiều tệp hoặc bộ nhớ là một ràng buộc, hãy xem xét sử dụng trình tạo:
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
Tùy chọn A: Lặp lại
for f in yield_files_with_extensions('.', '.txt'):
print(f)
Tùy chọn B: Nhận tất cả
files = [f for f in yield_files_with_extensions('.', '.txt')]
Một giải pháp có thể sao chép tương tự như một trong những 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
sử dụng mô-đun Python OS để tìm các tệp có phần mở rộng cụ thể.
ví dụ đơn giản ở đây:
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
Nhiều người dùng đã trả lời với os.walk
câu trả lời, bao gồm tất cả các tệp nhưng cũng có tất cả các thư mục và thư mục con và tệp của họ.
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)
Hoặc cho một nơi mà bạn không cần một máy phát điện:
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)
Nếu bạn định sử dụng kết quả khớp cho thứ khác, bạn có thể muốn đặt danh sách đó thay vì biểu thức trình tạo:
matches = [f for f in dirfiles if f.endswith(ext)]
Một phương pháp đơn giản bằng cách sử dụng for
vòng lặp:
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")
Mặc dù điều này có thể được thực hiện tổng quát hơn.