os.listdir()достанет вам все, что находится в каталоге - файлы и каталоги .
Если вам нужны только файлы, вы можете отфильтровать это, используя os.path:
from os import listdirfrom os.path import isfile, join
onlyfiles =[f for f in listdir(mypath)if isfile(join(mypath, f))]
или вы можете использовать, os.walk()что даст два списка для каждого каталога, который он посещает - разделение на файлы и каталоги для вас. Если вам нужен только верхний каталог, вы можете просто сломать его в первый раз
from os import walk
f =[]for(dirpath, dirnames, filenames)in walk(mypath):
f.extend(filenames)break
Немного проще: (_, _, filenames) = walk(mypath).next() (если вы уверены, что прогулка вернет хотя бы одно значение, которое должно быть.)
misterbee
9
Небольшая модификация для хранения полных путей: for (dirpath, dirnames, filenames) в os.walk (mypath): checkum_files.extend (os.path.join (dirpath, filename) для имени файла в именах файлов) break
okigan
150
f.extend(filenames)на самом деле не эквивалентно f = f + filenames. extendизменится fна месте, тогда как добавление создаст новый список в новой ячейке памяти. Это средство extendобычно более эффективно +, но иногда может привести к путанице, если несколько объектов содержат ссылки на список. Наконец, стоит отметить, что f += filenamesэто эквивалентно f.extend(filenames), а неf = f + filenames .
Бенджамин Ходжсон
30
@misterbee, ваше решение лучшее, только одно небольшое улучшение:_, _, filenames = next(walk(mypath), (None, None, []))
bgusach
35
в Python 3.x использовать(_, _, filenames) = next(os.walk(mypath))
ET-CS
1684
Я предпочитаю использовать globмодуль, так как он выполняет сопоставление с шаблоном и расширение.
чтобы уточнить, это не возвращает «полный путь»; он просто возвращает расширение шара, каким бы оно ни было. Например, учитывая /home/user/foo/bar/hello.txt, тогда, если работает в каталоге foo, то glob("bar/*.txt")вернется bar/hello.txt. Есть случаи, когда вам действительно нужен полный (то есть абсолютный) путь; для этих случаев, см. stackoverflow.com/questions/51520/…
не отвечает на этот вопрос. glob.glob("*")было бы.
Жан-Франсуа Фабр
прекрасный!!!! так .... x=glob.glob("../train/*.png")даст мне массив моих путей, если я знаю имя папки. Так круто!
Дженнифер Кросби
861
Получить список файлов с Python 2 и 3
os.listdir()
Как получить все файлы (и каталоги) в текущем каталоге (Python 3)
Ниже приведены простые методы извлечения только файлов в текущем каталоге с использованием os и listdir()функции в Python 3. Дальнейшее исследование покажет, как возвращать папки в каталоге, но у вас не будет файла в подкаталоге, для этого вы Можно использовать прогулку - обсудим позже).
import os
arr = os.listdir()print(arr)>>>['$RECYCLE.BIN','work.txt','3ebooks.txt','documents']
glob
Мне было легче выбрать файл того же типа или с чем-то общим. Посмотрите на следующий пример:
import glob
txtfiles =[]for file in glob.glob("*.txt"):
txtfiles.append(file)
glob с пониманием списка
import glob
mylist =[f for f in glob.glob("*.txt")]
glob с функцией
Функция возвращает список заданного расширения (.txt, .docx ecc.) В аргументе.
import globdef filebrowser(ext=""):"Returns files with an extension"return[f for f in glob.glob(f"*{ext}")]
x = filebrowser(".txt")print(x)>>>['example.txt','fb.txt','intro.txt','help.txt']
glob расширяя предыдущий код
Функция теперь возвращает список файлов, которые соответствуют строке, которую вы передаете в качестве аргумента
import globdef filesearch(word=""):"""Returns a list with all files with the word/extension in it"""
file =[]for f in glob.glob("*"):if word[0]==".":if f.endswith(word):
file.append(f)return fileelif word in f:
file.append(f)return filereturn file
lookfor ="example",".py"for w in lookfor:print(f"{w:10} found => {filesearch(w)}")
вывод
example found =>[].py found =>['search.py']
Получение полного пути с помощью os.path.abspath
Как вы заметили, у вас нет полного пути к файлу в приведенном выше коде. Если вам нужен абсолютный путь, вы можете использовать другую функцию os.pathвызываемого модуля _getfullpathname, указав в os.listdir()качестве аргумента файл, из которого вы получаете . Есть и другие способы получить полный путь, как мы проверим позже (я заменил, как это было предложено mexmex, _getfullpathname на abspath).
import os
files_path =[os.path.abspath(x)for x in os.listdir()]print(files_path)>>>['F:\\documenti\applications.txt','F:\\documenti\collections.txt']
Получить полный путь к типу файла во всех подкаталогах с помощью walk
Я нахожу это очень полезным для поиска материала во многих каталогах, и это помогло мне найти файл, имя которого я не запомнил:
import os# Getting the current work directory (cwd)
thisdir = os.getcwd()# r=root, d=directories, f = filesfor r, d, f in os.walk(thisdir):for file in f:if file.endswith(".docx"):print(os.path.join(r, file))
os.listdir(): получить файлы в текущем каталоге (Python 2)
В Python 2, если вы хотите получить список файлов в текущем каталоге, вы должны указать аргумент как «.» или os.getcwd () в методе os.listdir.
import os
arr = os.listdir('.')print(arr)>>>['$RECYCLE.BIN','work.txt','3ebooks.txt','documents']
Чтобы перейти в дерево каталогов
# Method 1
x = os.listdir('..')# Method 2
x= os.listdir('/')
Получить файлы: os.listdir()в определенном каталоге (Python 2 и 3)
import os
arr = os.listdir('F:\\python')print(arr)>>>['$RECYCLE.BIN','work.txt','3ebooks.txt','documents']
Получить файлы определенного подкаталога с os.listdir()
import os
x = os.listdir("./content")
os.walk('.') - Текущий каталог
import os
arr = next(os.walk('.'))[2]print(arr)>>>['5bs_Turismo1.pdf','5bs_Turismo1.pptx','esperienza.txt']
next(os.walk('.')) а также 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)>>> F:\\_python\\dict_class.py>>> F:\\_python\\programmi.txt
next(os.walk('F:\\') - получить полный путь - понимание списка
[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 - получить полный путь - все файлы в подкаталогах **
x =[os.path.join(r,file)for r,d,f in os.walk("F:\\_python")for file in f]print(x)>>>['F:\\_python\\dict.py','F:\\_python\\progr.txt','F:\\_python\\readl.py']
os.listdir() - получить только текстовые файлы
arr_txt =[x for x in os.listdir()if x.endswith(".txt")]print(arr_txt)>>>['work.txt','3ebooks.txt']
Использование, globчтобы получить полный путь к файлам
Если мне нужен абсолютный путь к файлам:
from path import pathfrom 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
Использование, os.path.isfileчтобы избежать каталогов в списке
import os.path
listOfFiles =[f for f in os.listdir()if os.path.isfile(f)]print(listOfFiles)>>>['a simple game.py','data.txt','decorator.py']
Использование pathlibиз 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
С list comprehension:
flist =[p for p in pathlib.Path('.').iterdir()if p.is_file()]
В качестве альтернативы используйте pathlib.Path()вместоpathlib.Path(".")
Используйте метод glob в pathlib.Path ()
import pathlib
py = pathlib.Path().glob("*.py")for file in py:print(file)>>> stack_overflow_list.py>>> stack_overflow_list_tkinter.py
Получить все и только файлы с os.walk
import os
x =[i[2]for i in os.walk('.')]
y=[]for t in x:for f in t:
y.append(f)print(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']
Получить только файлы с рядом и ходить в каталог
import os
x = next(os.walk('F://python'))[2]print(x)>>>['calculator.bat','calculator.py']
Получить только каталоги со следующим и ходить в каталог
import os
next(os.walk('F://python'))[1]# for the current dir use ('.')>>>['python3','others']
Получить все имена subdir с walk
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() от Python 3.5 и выше
import os
x =[f.name for f in os.scandir()if f.is_file()]print(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 oswith 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
Примеры:
Ex. 1: Сколько файлов в подкаталогах?
В этом примере мы ищем количество файлов, которые включены во весь каталог и его подкаталоги.
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 +=1return dir +" : "+ str(counter)+"files"print(count("F:\\python"))>>>'F:\\\python':12057 files'
Пример 2: Как скопировать все файлы из одного каталога в другой?
Сценарий для создания порядка на вашем компьютере, который находит все файлы типа (по умолчанию: pptx) и копирует их в новую папку.
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 +=1if counter >0:print('-'*30)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')>>> _compiti18\Compito Contabilità1\conti.txt
>>> _compiti18\Compito Contabilità1\modula4.txt
>>> _compiti18\Compito Contabilità1\moduloa4.txt
>>>------------------------>>>==>Foundin:`_compiti18`:3 files
Ex. 3: Как получить все файлы в текстовом файле
Если вы хотите создать текстовый файл со всеми именами файлов:
import os
mylist =""with open("filelist.txt","w", encoding="utf-8")as file:for eachfile in os.listdir():
mylist += eachfile +"\n"
file.write(mylist)
Пример: txt со всеми файлами жесткого диска
"""
We are going to save a txt file with all the files in your directory.
We will use the function walk()
"""import os
# see all the methods of os# print(*dir(os), sep=", ")
listafile =[]
percorso =[]with open("lista_file.txt","w", encoding='utf-8')as testo:for root, dirs, files in os.walk("D:\\"):for file in files:
listafile.append(file)
percorso.append(root +"\\"+ file)
testo.write(file +"\n")
listafile.sort()print("N. of files", len(listafile))with open("lista_file_ordinata.txt","w", encoding="utf-8")as testo_ordinato:for file in listafile:
testo_ordinato.write(file +"\n")with open("percorso.txt","w", encoding="utf-8")as file_percorso:for file in percorso:
file_percorso.write(file +"\n")
os.system("lista_file.txt")
os.system("lista_file_ordinata.txt")
os.system("percorso.txt")
Весь файл C: \ в одном текстовом файле
Это более короткая версия предыдущего кода. Измените папку, где начать поиск файлов, если вам нужно начать с другой позиции. Этот код генерирует 50 МБ текстового файла на моем компьютере с чем-то менее 500 000 строк с файлами с полным путем.
import os
with open("file.txt","w", encoding="utf-8")as filewrite:for r, d, f in os.walk("C:\\"):for file in f:
filewrite.write(f"{r + file}\n")
Как написать файл со всеми путями в папке типа
С помощью этой функции вы можете создать текстовый файл, который будет иметь имя типа искомого файла (например, pngfile.txt) со всем полным путем всех файлов этого типа. Это может быть полезно иногда, я думаю.
import os
def searchfiles(extension='.ttf', folder='H:\\'):"Create a txt file with all the file of a type"with open(extension[1:]+"file.txt","w", encoding="utf-8")as filewrite:for r, d, f in os.walk(folder):for file in f:if file.endswith(extension):
filewrite.write(f"{r + file}\n")# looking for png file (fonts) in the hard disk H:\
searchfiles('.png','H:\\')>>> H:\4bs_18\Dolphins5.png
>>> H:\4bs_18\Dolphins6.png
>>> H:\4bs_18\Dolphins7.png
>>> H:\5_18\marketing html\assets\imageslogo2.png
>>> H:\7z001.png
>>> H:\7z002.png
(Новое) Найти все файлы и открыть их с помощью графического интерфейса tkinter
Я просто хотел добавить в это 2019 небольшое приложение для поиска всех файлов в папке и иметь возможность открывать их, дважды щелкнув по имени файла в списке.
import tkinter as tk
import os
def searchfiles(extension='.txt', folder='H:\\'):"insert all files in the listbox"for r, d, f in os.walk(folder):for file in f:if file.endswith(extension):
lb.insert(0, r +"\\"+ file)def open_file():
os.startfile(lb.get(lb.curselection()[0]))
root = tk.Tk()
root.geometry("400x400")
bt = tk.Button(root, text="Search", command=lambda:searchfiles('.png','H:\\'))
bt.pack()
lb = tk.Listbox(root)
lb.pack(fill="both", expand=1)
lb.bind("<Double-Button>",lambda x: open_file())
root.mainloop()
Это смесь слишком многих ответов на вопросы, которые здесь не задавались. Может также стоить объяснить, что такое предостережения или рекомендуемые подходы. Мне не лучше знать один способ против 20 способов сделать то же самое, если я не знаю, какой из них более уместен, когда.
cs95
Хорошо, как можно скорее, я посмотрю на свой ответ и постараюсь сделать его более четким и с более полезной информацией о разнице между методами и т. Д.
Джованни Г. П.
Вы не должны определять расширение файла, проверяя, содержит ли имя файла подстроку. Это может вызвать много проблем. Я рекомендую всегда проверять, заканчивается ли имя файла конкретной подстрокой.
ni1ight
Хорошо, @ n1light Я изменил код ...
Джованни Г. Пи
813
import os
os.listdir("somedirectory")
вернет список всех файлов и каталогов в «somedirectory».
Это возвращает относительный путь к файлам по сравнению с полным путем, возвращаемымglob.glob
xji
22
@JIXiang: os.listdir()всегда возвращает простые имена файлов (не относительные пути). То, что glob.glob()возвращает, зависит от формата пути входного шаблона.
mklement0
os.listdir () -> Он всегда перечисляет каталог и файл в указанном месте. Есть ли способ перечислить только каталог, а не файлы?
RonyA
160
Однострочное решение для получения только списка файлов (без подкаталогов):
filenames = next(os.walk(path))[2]
или абсолютные пути:
paths =[os.path.join(path, fn)for fn in next(os.walk(path))[2]]
Только одна строка, если вы уже import os. Кажется менее кратким, чем glob()для меня.
ArtOfWarfare
4
проблема с glob состоит в том, что папка с именем'thing.something 'будет возвращена glob (' / home / adam /*.* ')
Remi
6
В OS X есть нечто, называемое комплектом. Это каталог, который обычно следует рассматривать как файл (например, .tar). Вы хотите, чтобы те рассматривались как файл или каталог? Использование glob()будет рассматривать его как файл. Ваш метод будет рассматривать его как каталог.
ArtOfWarfare
132
Получение полных путей к файлам из каталога и всех его подкаталогов
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")
Путь, который я указал в вышеупомянутой функции, содержал 3 файла - два из них в корневом каталоге, а другой - в подпапке «SUBFOLDER». Теперь вы можете делать такие вещи, как:
>>>import pathlib
>>>[p for p in pathlib.Path('.').iterdir()if p.is_file()]
Согласно PEP 428 , цель pathlibбиблиотеки - предоставить простую иерархию классов для обработки путей файловой системы и общих операций, которые пользователи выполняют над ними.
Спасибо! Я думаю, что это единственное решение, которое не возвращается напрямую list. Могли бы использовать p.nameвместо первого pальтернативно, если предпочтительнее.
Джеромей
1
Добро пожаловать! Я бы предпочел генерировать pathlib.Path()экземпляры, поскольку у них есть много полезных методов, которые я бы не хотел тратить впустую. Вы также можете вызвать str(p)их для имен путей.
Зиберт Адам
6
Примечание. os.scandirРешение будет более эффективным, чем os.listdirс os.path.is_fileпроверкой и т. П., Даже если вам нужно list(так что вы не извлекаете выгоду из ленивых итераций), потому что os.scandirиспользует предоставляемые ОС API-интерфейсы, которые предоставляют вам is_fileинформацию бесплатно во время итерации. , ни за файл туда и обратно на диск к statним на всех (на Windows, то DirEntryдобудет вам полная statинформацию бесплатно, на * NIX систем он должен statдля информации запредельного is_file, is_dirи т.д., но DirEntryкэша на первое statдля удобства).
ShadowRanger
1
Вы также можете использовать, entry.nameчтобы получить только имя файла или entry.pathполучить его полный путь. Нет больше os.path.join () повсюду.
user136036
56
Предварительные заметки
Хотя в тексте вопроса есть четкое различие между терминами файлов и каталогов , некоторые могут утверждать, что каталоги на самом деле являются специальными файлами.
Утверждение « все файлы каталога » можно интерпретировать двумя способами:
Все прямые (или уровня 1) только потомки
Все потомки во всем дереве каталогов (в том числе в подкаталогах)
Когда вопрос был задан, я представляю, что Python 2 был версией LTS , однако примеры кода будут выполняться Python 3 ( .5 ) (я буду поддерживать их как Python 2- совместимые, насколько это возможно; также любой код, принадлежащий Python, который я собираюсь опубликовать, взят из версии 3.5.4 - если не указано иное). Это имеет последствия, связанные с другим ключевым словом в вопросе: « добавить их в список »:
В версиях, предшествующих Python 2.2 , последовательности (итерируемые) в основном представляли собой списки (кортежи, множества, ...)
В Python 2.2 была введена концепция генератора ( [Python.Wiki]: Generators ) - любезно предоставлена [Python 3]: оператор yield ). Со временем начали появляться аналоги генератора функций, которые возвращали / работали со списками.
В Python 3 генератор является поведением по умолчанию
Не уверен, что возвращение списка все еще является обязательным (или генератор будет делать то же самое), но передача генератора в конструктор списка создаст из него список (и также потребит его). Приведенный ниже пример иллюстрирует различия в [Python 3]: map ( function, iterable, ... )
>>>import sys
>>> sys.version
'2.7.10 (default, Mar 8 2016, 15:02:46) [MSC v.1600 64 bit (AMD64)]'>>> m = map(lambda x: x,[1,2,3])# Just a dummy lambda function>>> m, type(m)([1,2,3],<type 'list'>)>>> len(m)3
>>>import sys
>>> sys.version
'3.5.4 (v3.5.4:3f56838, Aug 8 2017, 02:17:05) [MSC v.1900 64 bit (AMD64)]'>>> m = map(lambda x: x,[1,2,3])>>> m, type(m)(<map object at 0x000001B4257342B0>,<class'map'>)>>> len(m)Traceback(most recent call last):File"<stdin>", line 1,in<module>TypeError: object of type 'map' has no len()>>> lm0 = list(m)# Build a list from the generator>>> lm0, type(lm0)([1,2,3],<class'list'>)>>>>>> lm1 = list(m)# Build a list from the same generator>>> lm1, type(lm1)# Empty list now - generator already consumed([],<class'list'>)
Примеры будут основаны на каталоге с именем root_dir со следующей структурой (этот пример для Win , но я также использую то же дерево на Lnx ):
Вернуть список, содержащий имена записей в каталоге, заданных путем. Список в произвольном порядке, и не включает в себя специальные записи '.'и '..'...
>>>import os
>>> root_dir ="root_dir"# Path relative to current dir (os.getcwd())>>>>>> os.listdir(root_dir)# List all the items in root_dir['dir0','dir1','dir2','dir3','file0','file1']>>>>>>[item for item in os.listdir(root_dir)if os.path.isfile(os.path.join(root_dir, item))]# Filter items and only keep files (strip out directories)['file0','file1']
Более сложный пример ( code_os_listdir.py ):
import os
from pprint import pformat
def _get_dir_content(path, include_folders, recursive):
entries = os.listdir(path)for entry in entries:
entry_with_path = os.path.join(path, entry)if os.path.isdir(entry_with_path):if include_folders:yield entry_with_path
if recursive:for sub_entry in _get_dir_content(entry_with_path, include_folders, recursive):yield sub_entry
else:yield entry_with_path
def get_dir_content(path, include_folders=True, recursive=True, prepend_folder_name=True):
path_len = len(path)+ len(os.path.sep)for item in _get_dir_content(path, include_folders, recursive):yield item if prepend_folder_name else item[path_len:]def _get_dir_content_old(path, include_folders, recursive):
entries = os.listdir(path)
ret = list()for entry in entries:
entry_with_path = os.path.join(path, entry)if os.path.isdir(entry_with_path):if include_folders:
ret.append(entry_with_path)if recursive:
ret.extend(_get_dir_content_old(entry_with_path, include_folders, recursive))else:
ret.append(entry_with_path)return ret
def get_dir_content_old(path, include_folders=True, recursive=True, prepend_folder_name=True):
path_len = len(path)+ len(os.path.sep)return[item if prepend_folder_name else item[path_len:]for item in _get_dir_content_old(path, include_folders, recursive)]def main():
root_dir ="root_dir"
ret0 = get_dir_content(root_dir, include_folders=True, recursive=True, prepend_folder_name=True)
lret0 = list(ret0)print(ret0, len(lret0), pformat(lret0))
ret1 = get_dir_content_old(root_dir, include_folders=False, recursive=True, prepend_folder_name=False)print(len(ret1), pformat(ret1))if __name__ =="__main__":
main()
Примечания :
Есть две реализации:
Тот, который использует генераторы (конечно, здесь это кажется бесполезным, так как я немедленно конвертирую результат в список)
Классический (имена функций заканчиваются на _old )
Используется рекурсия (чтобы попасть в подкаталоги)
Для каждой реализации есть две функции:
Тот, который начинается с подчеркивания ( _ ): «private» (не должен вызываться напрямую) - это делает всю работу
Открытый (обертка поверх предыдущего): он просто удаляет начальный путь (если требуется) из возвращенных записей. Это уродливая реализация, но это единственная идея, с которой я мог прийти в этот момент
С точки зрения производительности генераторы, как правило, немного быстрее (учитывая время создания и итерации ), но я не проверял их в рекурсивных функциях, а также я перебираю функции внутри внутренних генераторов - не знаю, как производительность дружелюбный
Поиграйте с аргументами, чтобы получить разные результаты
Выход :
(py35x64_test) E:\Work\Dev\StackOverflow\q003207219>"e:\Work\Dev\VEnvs\py35x64_test\Scripts\python.exe""code_os_listdir.py"<generator object get_dir_content at 0x000001BDDBB3DF10>22['root_dir\\dir0','root_dir\\dir0\\dir00','root_dir\\dir0\\dir00\\dir000','root_dir\\dir0\\dir00\\dir000\\file0000','root_dir\\dir0\\dir00\\file000','root_dir\\dir0\\dir01','root_dir\\dir0\\dir01\\file010','root_dir\\dir0\\dir01\\file011','root_dir\\dir0\\dir02','root_dir\\dir0\\dir02\\dir020','root_dir\\dir0\\dir02\\dir020\\dir0200','root_dir\\dir1','root_dir\\dir1\\file10','root_dir\\dir1\\file11','root_dir\\dir1\\file12','root_dir\\dir2','root_dir\\dir2\\dir20','root_dir\\dir2\\dir20\\file200','root_dir\\dir2\\file20','root_dir\\dir3','root_dir\\file0','root_dir\\file1']11['dir0\\dir00\\dir000\\file0000','dir0\\dir00\\file000','dir0\\dir01\\file010','dir0\\dir01\\file011','dir1\\file10','dir1\\file11','dir1\\file12','dir2\\dir20\\file200','dir2\\file20','file0','file1']
Возвращает итератор os.DirEntry объектов , соответствующих записей в каталоге заданной траектории . Записи приводятся в произвольном порядке, а специальные записи '.'и '..'не включены.
Использование scandir () вместо listdir () может значительно повысить производительность кода, который также нуждается в информации о типе файла или атрибуте файла, поскольку объекты os.DirEntry предоставляют эту информацию, если операционная система предоставляет ее при сканировании каталога. Все методы os.DirEntry могут выполнять системный вызов, но для is_dir () и is_file () обычно требуется только системный вызов для символических ссылок; os.DirEntry.stat () всегда требует системного вызова в Unix, но требует только одного для символических ссылок в Windows.
>>>import os
>>> root_dir = os.path.join(".","root_dir")# Explicitly prepending current directory>>> root_dir
'.\\root_dir'>>>>>> scandir_iterator = os.scandir(root_dir)>>> scandir_iterator
<nt.ScandirIterator object at 0x00000268CF4BC140>>>>[item.path for item in scandir_iterator]['.\\root_dir\\dir0','.\\root_dir\\dir1','.\\root_dir\\dir2','.\\root_dir\\dir3','.\\root_dir\\file0','.\\root_dir\\file1']>>>>>>[item.path for item in scandir_iterator]# Will yield an empty list as it was consumed by previous iteration (automatically performed by the list comprehension)[]>>>>>> scandir_iterator = os.scandir(root_dir)# Reinitialize the generator>>>for item in scandir_iterator :...if os.path.isfile(item.path):...print(item.name)...
file0
file1
Примечания :
Это похоже на os.listdir
Но он также более гибкий (и предлагает больше функциональности), больше Python ic (а в некоторых случаях быстрее)
Генерируйте имена файлов в дереве каталогов, обходя дерево сверху вниз или снизу вверх. Для каждого каталога в дереве каталогов с корнем в вершине ( в том числе и сверху сам), он дает 3-кортеж ( dirpath, dirnames, filenames).
>>>import os
>>> root_dir = os.path.join(os.getcwd(),"root_dir")# Specify the full path>>> root_dir
'E:\\Work\\Dev\\StackOverflow\\q003207219\\root_dir'>>>>>> walk_generator = os.walk(root_dir)>>> root_dir_entry = next(walk_generator)# First entry corresponds to the root dir (passed as an argument)>>> root_dir_entry
('E:\\Work\\Dev\\StackOverflow\\q003207219\\root_dir',['dir0','dir1','dir2','dir3'],['file0','file1'])>>>>>> root_dir_entry[1]+ root_dir_entry[2]# Display dirs and files (direct descendants) in a single list['dir0','dir1','dir2','dir3','file0','file1']>>>>>>[os.path.join(root_dir_entry[0], item)for item in root_dir_entry[1]+ root_dir_entry[2]]# Display all the entries in the previous list by their full path['E:\\Work\\Dev\\StackOverflow\\q003207219\\root_dir\\dir0','E:\\Work\\Dev\\StackOverflow\\q003207219\\root_dir\\dir1','E:\\Work\\Dev\\StackOverflow\\q003207219\\root_dir\\dir2','E:\\Work\\Dev\\StackOverflow\\q003207219\\root_dir\\dir3','E:\\Work\\Dev\\StackOverflow\\q003207219\\root_dir\\file0','E:\\Work\\Dev\\StackOverflow\\q003207219\\root_dir\\file1']>>>>>>for entry in walk_generator:# Display the rest of the elements (corresponding to every subdir)...print(entry)...('E:\\Work\\Dev\\StackOverflow\\q003207219\\root_dir\\dir0',['dir00','dir01','dir02'],[])('E:\\Work\\Dev\\StackOverflow\\q003207219\\root_dir\\dir0\\dir00',['dir000'],['file000'])('E:\\Work\\Dev\\StackOverflow\\q003207219\\root_dir\\dir0\\dir00\\dir000',[],['file0000'])('E:\\Work\\Dev\\StackOverflow\\q003207219\\root_dir\\dir0\\dir01',[],['file010','file011'])('E:\\Work\\Dev\\StackOverflow\\q003207219\\root_dir\\dir0\\dir02',['dir020'],[])('E:\\Work\\Dev\\StackOverflow\\q003207219\\root_dir\\dir0\\dir02\\dir020',['dir0200'],[])('E:\\Work\\Dev\\StackOverflow\\q003207219\\root_dir\\dir0\\dir02\\dir020\\dir0200',[],[])('E:\\Work\\Dev\\StackOverflow\\q003207219\\root_dir\\dir1',[],['file10','file11','file12'])('E:\\Work\\Dev\\StackOverflow\\q003207219\\root_dir\\dir2',['dir20'],['file20'])('E:\\Work\\Dev\\StackOverflow\\q003207219\\root_dir\\dir2\\dir20',[],['file200'])('E:\\Work\\Dev\\StackOverflow\\q003207219\\root_dir\\dir3',[],[])
Примечания :
Под сценами он использует os.scandir( os.listdirна старых версиях)
Это делает тяжелую работу, возвращаясь в подпапках
Возврат возможно пустого списка имен путей , которые соответствуют пути , который должен быть строкой, содержащей спецификацию пути. pathname может быть абсолютным (как /usr/src/Python-1.5/Makefile) или относительным (как ../../Tools/*/*.gif) и может содержать подстановочные знаки в стиле оболочки. Сломанные символические ссылки включены в результаты (как в оболочке). ... Изменено в версии 3.5 : Поддержка рекурсивных глобусов с использованием « **».
>>>import glob, os
>>> wildcard_pattern ="*">>> root_dir = os.path.join("root_dir", wildcard_pattern)# Match every file/dir name>>> root_dir
'root_dir\\*'>>>>>> glob_list = glob.glob(root_dir)>>> glob_list
['root_dir\\dir0','root_dir\\dir1','root_dir\\dir2','root_dir\\dir3','root_dir\\file0','root_dir\\file1']>>>>>>[item.replace("root_dir"+ os.path.sep,"")for item in glob_list]# Strip the dir name and the path separator from begining['dir0','dir1','dir2','dir3','file0','file1']>>>>>>for entry in glob.iglob(root_dir +"*", recursive=True):...print(entry)...
root_dir\
root_dir\dir0
root_dir\dir0\dir00
root_dir\dir0\dir00\dir000
root_dir\dir0\dir00\dir000\file0000
root_dir\dir0\dir00\file000
root_dir\dir0\dir01
root_dir\dir0\dir01\file010
root_dir\dir0\dir01\file011
root_dir\dir0\dir02
root_dir\dir0\dir02\dir020
root_dir\dir0\dir02\dir020\dir0200
root_dir\dir1
root_dir\dir1\file10
root_dir\dir1\file11
root_dir\dir1\file12
root_dir\dir2
root_dir\dir2\dir20
root_dir\dir2\dir20\file200
root_dir\dir2\file20
root_dir\dir3
root_dir\file0
root_dir\file1
Примечания :
Пользы os.listdir
Для больших деревьев (особенно , если рекурсивная включен), iglob является предпочтительным
Позволяет расширенную фильтрацию по имени (из-за подстановочных знаков)
>>>import pathlib
>>> root_dir ="root_dir">>> root_dir_instance = pathlib.Path(root_dir)>>> root_dir_instance
WindowsPath('root_dir')>>> root_dir_instance.name
'root_dir'>>> root_dir_instance.is_dir()True>>>>>>[item.name for item in root_dir_instance.glob("*")]# Wildcard searching for all direct descendants['dir0','dir1','dir2','dir3','file0','file1']>>>>>>[os.path.join(item.parent.name, item.name)for item in root_dir_instance.glob("*")ifnot item.is_dir()]# Display paths (including parent) for files only['root_dir\\file0','root_dir\\file1']
def listdir(path):"""List directory contents, using cache."""try:
cached_mtime, list = cache[path]del cache[path]exceptKeyError:
cached_mtime, list =-1,[]
mtime = os.stat(path).st_mtime
if mtime != cached_mtime:
list = os.listdir(path)
list.sort()
cache[path]= mtime, list
return list
ctypes - это библиотека внешних функций для Python. Он предоставляет C-совместимые типы данных и позволяет вызывать функции в DLL или общих библиотеках. Это может быть использовано, чтобы обернуть эти библиотеки в чистый Python.
LinuxDirent64 - это представление ctypes для struct dirent64 из [man7]: dirent.h (0P) (как и константы DT_ ) с моей машины: Ubtu 16 x64 ( 4.10.0-40-generic и libc6-dev: amd64 ). В других вариантах / версиях определение структуры может отличаться, и если это так, псевдоним ctypes должен быть обновлен, в противном случае он приведет к неопределенному поведению
Возвращает данные в os.walkформате. Я не удосужился сделать его рекурсивным, но, исходя из существующего кода, это было бы довольно тривиальной задачей
На Win все также выполнимо , данные (библиотеки, функции, структуры, константы, ...) отличаются
Выход :
[cfati@cfati-ubtu16x64-0:~/Work/Dev/StackOverflow/q003207219]>./code_ctypes.py
3.5.2(default,Nov122018,13:43:14)[GCC 5.4.020160609] on linux
['root_dir',['dir2','dir1','dir3','dir0'],['file1','file0']]
Получает список совпадающих имен файлов с помощью Windows Unicode API. Интерфейс для API FindFirstFileW / FindNextFileW / Find close functions.
>>>import os, win32file, win32con
>>> root_dir ="root_dir">>> wildcard ="*">>> root_dir_wildcard = os.path.join(root_dir, wildcard)>>> entry_list = win32file.FindFilesW(root_dir_wildcard)>>> len(entry_list)# Don't display the whole content as it's too long8>>>[entry[-2]for entry in entry_list]# Only display the entry names['.','..','dir0','dir1','dir2','dir3','file0','file1']>>>>>>[entry[-2]for entry in entry_list if entry[0]& win32con.FILE_ATTRIBUTE_DIRECTORY and entry[-2]notin(".","..")]# Filter entries and only display dir names (except self and parent)['dir0','dir1','dir2','dir3']>>>>>>[os.path.join(root_dir, entry[-2])for entry in entry_list if entry[0]&(win32con.FILE_ATTRIBUTE_NORMAL | win32con.FILE_ATTRIBUTE_ARCHIVE)]# Only display file "full" names['root_dir\\file0','root_dir\\file1']
Ссылка на документацию от ActiveState , так как я не нашел никакой официальной документации PyWin32
Установите какой-нибудь (другой) сторонний пакет, который делает свое дело
Скорее всего, будет опираться на один (или несколько) из вышеперечисленных (возможно, с небольшими настройками)
Примечания :
Код должен быть переносимым (кроме мест, предназначенных для определенной области - которые отмечены) или крестиком:
платформа ( Nix , Win ,)
Версия Python (2, 3,)
Множество стилей пути (абсолютный, родственник) были использованы в вышеупомянутых вариантах, чтобы проиллюстрировать тот факт, что используемые «инструменты» являются гибкими в этом направлении
_get_dir_content (из пункта №1. ) может быть реализован с использованием любого из этих подходов (некоторые потребуют больше работы, а некоторые меньше)
Может быть проделана некоторая расширенная фильтрация (вместо просто file vs. dir): например, аргумент include_folders может быть заменен другим (например, filter_func ), который будет функцией, которая принимает путь в качестве аргумента: filter_func=lambda x: True(это не раздвигает что-нибудь) и внутри _get_dir_content что-то вроде: if not filter_func(entry_with_path): continue(если функция завершается с ошибкой для одной записи, она будет пропущена), но чем сложнее становится код, тем дольше будет выполняться
Нота бене! Поскольку используется рекурсия, я должен упомянуть, что я провел несколько тестов на своем ноутбуке ( Win 10 x64 ), совершенно не связанных с этой проблемой, и когда уровень рекурсии достигал значений где-то в диапазоне (990 .. 1000) ( предел рекурсии - 1000 (по умолчанию)), я получил StackOverflow :). Если дерево каталогов превышает этот предел (я не эксперт FS , поэтому я не знаю, возможно ли это вообще), это может быть проблемой.
Я должен также упомянуть, что я не пытался увеличить предел рекурсии, потому что у меня нет опыта в этой области (насколько я могу его увеличить, прежде чем увеличивать стек в ОСуровень), но в теории всегда будет возможность отказа, если глубина dir больше максимально возможного предела рекурсии (на этой машине)
Примеры кода приведены только для демонстрации. Это означает, что я не принял во внимание обработку ошибок (я не думаю, что есть какой- либо блок try / кроме / else / finally ), поэтому код не является устойчивым (причина в том, чтобы сделать его максимально простым и коротким, насколько это возможно). ). Для производства должна быть добавлена обработка ошибок
Другие подходы:
Используйте Python только в качестве оболочки
Все сделано с использованием другой технологии
Эта технология вызывается из Python
Самый известный вариант, который я знаю, это то, что я называю подходом системного администратора :
Используйте Python (или любой другой язык программирования в этом отношении) для выполнения команд оболочки (и анализа их выходных данных)
Некоторые считают это аккуратным хаком
Я считаю, что это больше похоже на неудачный обходной путь ( gainarie ), поскольку само по себе действие выполняется из оболочки ( в данном случае cmd ) и, следовательно, не имеет ничего общего с Python .
Фильтрация ( grep/ findstr) или форматирование вывода могут быть выполнены с обеих сторон, но я не буду настаивать на этом. Кроме того, я сознательно использовал os.systemвместо subprocess.Popen.
В общем случае такого подхода следует избегать, поскольку если какой-либо формат вывода команды немного отличается в зависимости от версий / разновидностей ОС , код синтаксического анализа также должен быть адаптирован; не говоря уже о различиях между локалями).
Мне очень понравился ответ Адамка , предлагающий использовать его glob()из одноименного модуля. Это позволяет вам соответствовать шаблону с *s.
Но, как отмечали другие люди в комментариях, они glob()могут быть сбиты с толку из-за непоследовательных направлений. Чтобы помочь с этим, я предлагаю вам использовать join()и expanduser()функцию в os.pathмодуле, и , возможно, getcwd()функций в osмодуле, а также.
В качестве примеров:
from glob import glob
# Return everything under C:\Users\admin that contains a folder called wlp.
glob('C:\Users\admin\*\wlp')
Вышеуказанное ужасно - путь был жестко задан и будет работать только в Windows между именем диска и \жестко закодированным в путь.
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'))
Вышеописанное работает лучше, но оно опирается на имя папки, Usersкоторое часто встречается в Windows и не так часто встречается в других ОС. Это также зависит от пользователя, имеющего определенное имя 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'))
Это прекрасно работает на всех платформах.
Еще один отличный пример, который отлично работает на разных платформах и делает что-то немного другое:
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'))
Надеюсь, что эти примеры помогут вам увидеть мощь нескольких функций, которые вы можете найти в стандартных модулях библиотеки Python.
def list_files(path):# returns a list of names (with extension, without full path) of all files # in folder path
files =[]for name in os.listdir(path):if os.path.isfile(os.path.join(path, name)):
files.append(name)return files
Для больших результатов вы можете использовать listdir()метод osмодуля вместе с генератором (генератор - мощный итератор, который сохраняет свое состояние, помните?). Следующий код прекрасно работает с обеими версиями: Python 2 и Python 3.
Вот код:
import os
def files(path):for file in os.listdir(path):if os.path.isfile(os.path.join(path, file)):yield file
for file in files("."):print(file)
listdir()Метод возвращает список записей для данного каталога. Метод os.path.isfile()возвращает, Trueесли данная запись является файлом. И yieldоператор выходит из функции, но сохраняет свое текущее состояние и возвращает только имя записи, обнаруженной как файл. Все вышеизложенное позволяет нам зациклить функцию генератора.
Примечание: os.path.abspath(f)будет несколько более дешевой заменой os.path.join(os.getcwd(),f).
ShadowRanger
Я бы по-прежнему был более эффективен, если бы вы начали cwd = os.path.abspath('.'), а затем использовали cwdвместо этого '.'и os.getcwd()во всем, чтобы избежать нагрузки на избыточные системные вызовы.
То же самое может быть достигнуто только в одной строке с pathlib:filter(Path.is_file, Path().rglob('*'))
Георгий
9
Однажды один мудрый учитель сказал мне:
Когда есть несколько установленных способов сделать что-то, ни один из них не подходит для всех случаев.
Таким образом, я добавлю решение для подмножества проблемы: довольно часто мы только хотим проверить, соответствует ли файл начальной и конечной строкам, не заходя в подкаталоги. Таким образом, нам нужна функция, которая возвращает список имен файлов, например:
Если вы хотите сначала объявить две функции, это можно сделать:
def file_filter(filename, radical='', extension=''):"Check if a filename matches a radical and extension"ifnot filename:returnFalse
filename = filename.strip()return(filename.startswith(radical)and filename.endswith(extension))def dir_filter(dirname='', radical='', extension=''):"Filter filenames in directory according to radical and extension"ifnot dirname:
dirname ='.'return[filename for filename in os.listdir(dirname)if file_filter(filename, radical, extension)]
Это решение может быть легко обобщено с помощью регулярных выражений (и вы можете добавить patternаргумент, если вы не хотите, чтобы ваши шаблоны всегда придерживались начала или конца имени файла).
Еще один очень читаемый вариант для Python 3.4+ использует pathlib.Path.glob:
from pathlib importPath
folder ='/foo'[f for f inPath(folder).glob('*')if f.is_file()]
Это проще сделать более конкретно, например, искать только исходные файлы Python, которые не являются символическими ссылками, также во всех подкаталогах:
[f for f inPath(folder).glob('**/*.py')ifnot f.is_symlink()]
Вот моя универсальная функция для этого. Он возвращает список путей к файлам, а не имен файлов, так как я обнаружил, что это более полезно. У него есть несколько необязательных аргументов, которые делают его универсальным. Например, я часто использую его с аргументами вроде pattern='*.txt'или subfolders=True.
import os
import fnmatch
def list_paths(folder='.', pattern='*', case_sensitive=False, subfolders=False):"""Return a list of the file paths matching the pattern in the specified
folder, optionally including files inside subfolders.
"""
match = fnmatch.fnmatchcase if case_sensitive else fnmatch.fnmatch
walked = os.walk(folder)if subfolders else[next(os.walk(folder))]return[os.path.join(root, f)for root, dirnames, filenames in walked
for f in filenames if match(f, pattern)]
Я предоставлю пример одного лайнера, где исходный путь и тип файла могут быть предоставлены в качестве входных данных. Код возвращает список имен файлов с расширением csv. Использование . в случае, если все файлы должны быть возвращены. Это также рекурсивно сканирует подкаталоги.
[y for x in os.walk(sourcePath) for y in glob(os.path.join(x[0], '*.csv'))]
Измените расширения файлов и исходный путь по мере необходимости.
Если вы собираетесь использовать glob, то просто используйте glob('**/*.csv', recursive=True). Нет необходимости сочетать это с os.walk()рекурсией ( recursiveи **поддерживаются начиная с Python 3.5).
Ответы:
os.listdir()
достанет вам все, что находится в каталоге - файлы и каталоги .Если вам нужны только файлы, вы можете отфильтровать это, используя
os.path
:или вы можете использовать,
os.walk()
что даст два списка для каждого каталога, который он посещает - разделение на файлы и каталоги для вас. Если вам нужен только верхний каталог, вы можете просто сломать его в первый разисточник
(_, _, filenames) = walk(mypath).next()
(если вы уверены, что прогулка вернет хотя бы одно значение, которое должно быть.)f.extend(filenames)
на самом деле не эквивалентноf = f + filenames
.extend
изменитсяf
на месте, тогда как добавление создаст новый список в новой ячейке памяти. Это средствоextend
обычно более эффективно+
, но иногда может привести к путанице, если несколько объектов содержат ссылки на список. Наконец, стоит отметить, чтоf += filenames
это эквивалентноf.extend(filenames)
, а неf = f + filenames
._, _, filenames = next(walk(mypath), (None, None, []))
(_, _, filenames) = next(os.walk(mypath))
Я предпочитаю использовать
glob
модуль, так как он выполняет сопоставление с шаблоном и расширение.Он вернет список с запрошенными файлами:
источник
/home/user/foo/bar/hello.txt
, тогда, если работает в каталогеfoo
, тоglob("bar/*.txt")
вернетсяbar/hello.txt
. Есть случаи, когда вам действительно нужен полный (то есть абсолютный) путь; для этих случаев, см. stackoverflow.com/questions/51520/…glob.glob("*")
было бы.x=glob.glob("../train/*.png")
даст мне массив моих путей, если я знаю имя папки. Так круто!Как получить все файлы (и каталоги) в текущем каталоге (Python 3)
Ниже приведены простые методы извлечения только файлов в текущем каталоге с использованием
os
иlistdir()
функции в Python 3. Дальнейшее исследование покажет, как возвращать папки в каталоге, но у вас не будет файла в подкаталоге, для этого вы Можно использовать прогулку - обсудим позже).Мне было легче выбрать файл того же типа или с чем-то общим. Посмотрите на следующий пример:
Функция возвращает список заданного расширения (.txt, .docx ecc.) В аргументе.
Функция теперь возвращает список файлов, которые соответствуют строке, которую вы передаете в качестве аргумента
вывод
Как вы заметили, у вас нет полного пути к файлу в приведенном выше коде. Если вам нужен абсолютный путь, вы можете использовать другую функцию
os.path
вызываемого модуля_getfullpathname
, указав вos.listdir()
качестве аргумента файл, из которого вы получаете . Есть и другие способы получить полный путь, как мы проверим позже (я заменил, как это было предложено mexmex, _getfullpathname наabspath
).Я нахожу это очень полезным для поиска материала во многих каталогах, и это помогло мне найти файл, имя которого я не запомнил:
В Python 2, если вы хотите получить список файлов в текущем каталоге, вы должны указать аргумент как «.» или os.getcwd () в методе os.listdir.
Если мне нужен абсолютный путь к файлам:
С
list comprehension
:В качестве альтернативы используйте
pathlib.Path()
вместоpathlib.Path(".")
В этом примере мы ищем количество файлов, которые включены во весь каталог и его подкаталоги.
Сценарий для создания порядка на вашем компьютере, который находит все файлы типа (по умолчанию: pptx) и копирует их в новую папку.
Если вы хотите создать текстовый файл со всеми именами файлов:
С помощью этой функции вы можете создать текстовый файл, который будет иметь имя типа искомого файла (например, pngfile.txt) со всем полным путем всех файлов этого типа. Это может быть полезно иногда, я думаю.
источник
вернет список всех файлов и каталогов в «somedirectory».
источник
glob.glob
os.listdir()
всегда возвращает простые имена файлов (не относительные пути). То, чтоglob.glob()
возвращает, зависит от формата пути входного шаблона.Однострочное решение для получения только списка файлов (без подкаталогов):
или абсолютные пути:
источник
import os
. Кажется менее кратким, чемglob()
для меня.glob()
будет рассматривать его как файл. Ваш метод будет рассматривать его как каталог.Получение полных путей к файлам из каталога и всех его подкаталогов
print full_file_paths
который напечатает список:['/Users/johnny/Desktop/TEST/file1.txt', '/Users/johnny/Desktop/TEST/file2.txt', '/Users/johnny/Desktop/TEST/SUBFOLDER/file3.dat']
При желании вы можете открыть и прочитать содержимое или сосредоточиться только на файлах с расширением «.dat», как показано в коде ниже:
/Users/johnny/Desktop/TEST/SUBFOLDER/file3.dat
источник
Начиная с версии 3.4 для этого есть встроенные итераторы, которые намного эффективнее, чем
os.listdir()
:pathlib
: Новое в версии 3.4.Согласно PEP 428 , цель
pathlib
библиотеки - предоставить простую иерархию классов для обработки путей файловой системы и общих операций, которые пользователи выполняют над ними.os.scandir()
: Новое в версии 3.5.Обратите внимание, что
os.walk()
используетсяos.scandir()
вместоos.listdir()
версии 3.5, а его скорость увеличена в 2-20 раз согласно PEP 471 .Позвольте мне также рекомендовать прочитать комментарий ShadowRanger ниже.
источник
list
. Могли бы использоватьp.name
вместо первогоp
альтернативно, если предпочтительнее.pathlib.Path()
экземпляры, поскольку у них есть много полезных методов, которые я бы не хотел тратить впустую. Вы также можете вызватьstr(p)
их для имен путей.os.scandir
Решение будет более эффективным, чемos.listdir
сos.path.is_file
проверкой и т. П., Даже если вам нужноlist
(так что вы не извлекаете выгоду из ленивых итераций), потому чтоos.scandir
использует предоставляемые ОС API-интерфейсы, которые предоставляют вамis_file
информацию бесплатно во время итерации. , ни за файл туда и обратно на диск кstat
ним на всех (на Windows, тоDirEntry
добудет вам полнаяstat
информацию бесплатно, на * NIX систем он долженstat
для информации запредельногоis_file
,is_dir
и т.д., ноDirEntry
кэша на первоеstat
для удобства).entry.name
чтобы получить только имя файла илиentry.path
получить его полный путь. Нет больше os.path.join () повсюду.Предварительные заметки
Когда вопрос был задан, я представляю, что Python 2 был версией LTS , однако примеры кода будут выполняться Python 3 ( .5 ) (я буду поддерживать их как Python 2- совместимые, насколько это возможно; также любой код, принадлежащий Python, который я собираюсь опубликовать, взят из версии 3.5.4 - если не указано иное). Это имеет последствия, связанные с другим ключевым словом в вопросе: « добавить их в список »:
Примеры будут основаны на каталоге с именем root_dir со следующей структурой (этот пример для Win , но я также использую то же дерево на Lnx ):
Решения
Программные подходы:
[Python 3]: ос. listdir ( путь = '.' )
Более сложный пример ( code_os_listdir.py ):
Примечания :
Выход :
[Python 3]: ос. ScanDir ( путь = '' ) ( Python 3.5 + портировать: [PyPI]: ScanDir )
Примечания :
os.listdir
[Python 3]: ос. ходьба ( top, topdown = True, onerror = None, последующие ссылки = False )
Примечания :
os.scandir
(os.listdir
на старых версиях)[Питон 3]: шар. glob ( pathname, *, recursive = False ) ( [Python 3]: glob. iglob ( pathname, *, recursive = False ) )
Примечания :
os.listdir
[Python 3]: class pathlib. Путь ( * pathsegments ) ( Python 3.4 +, обратный порт : [PyPI]: pathlib2 )
Примечания :
[Python 2]: dircache.listdir (путь) ( только Python 2 )
os.listdir
с кэшированием[man7]: OPENDIR (3) / [man7]: READDIR (3) / [man7]: CLOSEDIR (3) через [Python 3]: ctypes - библиотека сторонних функций для Python ( специфична для POSIX )
code_ctypes.py :
Примечания :
os.walk
формате. Я не удосужился сделать его рекурсивным, но, исходя из существующего кода, это было бы довольно тривиальной задачейВыход :
[ActiveState.Docs]: win32file.FindFilesW ( зависит от выигрыша )
Примечания :
win32file.FindFilesW
является частью [GitHub]: mhammond / pywin32 - Python для Windows (pywin32) расширений , который является Python обертку над WINAPI sПримечания :
Код должен быть переносимым (кроме мест, предназначенных для определенной области - которые отмечены) или крестиком:
Множество стилей пути (абсолютный, родственник) были использованы в вышеупомянутых вариантах, чтобы проиллюстрировать тот факт, что используемые «инструменты» являются гибкими в этом направлении
os.listdir
иos.scandir
используйте opendir / readdir / closedir ( [MS.Docs]: функция FindFirstFileW / [MS.Docs]: функция FindNextFileW / [MS.Docs]: функция FindClose ) (через [GitHub]: python / cpython - (master) cpython / Модули / posixmodule.c )win32file.FindFilesW
также использует эти ( специфичные для Win ) функции (через [GitHub]: mhammond / pywin32 - (master) pywin32 / win32 / src / win32file.i )_get_dir_content (из пункта №1. ) может быть реализован с использованием любого из этих подходов (некоторые потребуют больше работы, а некоторые меньше)
filter_func=lambda x: True
(это не раздвигает что-нибудь) и внутри _get_dir_content что-то вроде:if not filter_func(entry_with_path): continue
(если функция завершается с ошибкой для одной записи, она будет пропущена), но чем сложнее становится код, тем дольше будет выполнятьсяНота бене! Поскольку используется рекурсия, я должен упомянуть, что я провел несколько тестов на своем ноутбуке ( Win 10 x64 ), совершенно не связанных с этой проблемой, и когда уровень рекурсии достигал значений где-то в диапазоне (990 .. 1000) ( предел рекурсии - 1000 (по умолчанию)), я получил StackOverflow :). Если дерево каталогов превышает этот предел (я не эксперт FS , поэтому я не знаю, возможно ли это вообще), это может быть проблемой.
Я должен также упомянуть, что я не пытался увеличить предел рекурсии, потому что у меня нет опыта в этой области (насколько я могу его увеличить, прежде чем увеличивать стек в ОСуровень), но в теории всегда будет возможность отказа, если глубина dir больше максимально возможного предела рекурсии (на этой машине)
Примеры кода приведены только для демонстрации. Это означает, что я не принял во внимание обработку ошибок (я не думаю, что есть какой- либо блок try / кроме / else / finally ), поэтому код не является устойчивым (причина в том, чтобы сделать его максимально простым и коротким, насколько это возможно). ). Для производства должна быть добавлена обработка ошибок
Другие подходы:
Используйте Python только в качестве оболочки
Самый известный вариант, который я знаю, это то, что я называю подходом системного администратора :
grep
/findstr
) или форматирование вывода могут быть выполнены с обеих сторон, но я не буду настаивать на этом. Кроме того, я сознательно использовалos.system
вместоsubprocess.Popen
.В общем случае такого подхода следует избегать, поскольку если какой-либо формат вывода команды немного отличается в зависимости от версий / разновидностей ОС , код синтаксического анализа также должен быть адаптирован; не говоря уже о различиях между локалями).
источник
Мне очень понравился ответ Адамка , предлагающий использовать его
glob()
из одноименного модуля. Это позволяет вам соответствовать шаблону с*
s.Но, как отмечали другие люди в комментариях, они
glob()
могут быть сбиты с толку из-за непоследовательных направлений. Чтобы помочь с этим, я предлагаю вам использоватьjoin()
иexpanduser()
функцию вos.path
модуле, и , возможно,getcwd()
функций вos
модуле, а также.В качестве примеров:
Вышеуказанное ужасно - путь был жестко задан и будет работать только в Windows между именем диска и
\
жестко закодированным в путь.Вышеописанное работает лучше, но оно опирается на имя папки,
Users
которое часто встречается в Windows и не так часто встречается в других ОС. Это также зависит от пользователя, имеющего определенное имяadmin
.Это прекрасно работает на всех платформах.
Еще один отличный пример, который отлично работает на разных платформах и делает что-то немного другое:
Надеюсь, что эти примеры помогут вам увидеть мощь нескольких функций, которые вы можете найти в стандартных модулях библиотеки Python.
источник
**
работает столько, сколько вы установилиrecursive = True
. Смотрите документы здесь: docs.python.org/3.5/library/glob.html#glob.globисточник
Если вы ищете реализацию find для Python , я часто использую этот рецепт:
Поэтому я сделал из него пакет PyPI , а также есть репозиторий GitHub . Я надеюсь, что кто-то найдет это потенциально полезным для этого кода.
источник
Для больших результатов вы можете использовать
listdir()
методos
модуля вместе с генератором (генератор - мощный итератор, который сохраняет свое состояние, помните?). Следующий код прекрасно работает с обеими версиями: Python 2 и Python 3.Вот код:
listdir()
Метод возвращает список записей для данного каталога. Методos.path.isfile()
возвращает,True
если данная запись является файлом. Иyield
оператор выходит из функции, но сохраняет свое текущее состояние и возвращает только имя записи, обнаруженной как файл. Все вышеизложенное позволяет нам зациклить функцию генератора.источник
Возвращая список абсолютных путей к файлам, не попадает в подкаталоги
источник
os.path.abspath(f)
будет несколько более дешевой заменойos.path.join(os.getcwd(),f)
.cwd = os.path.abspath('.')
, а затем использовалиcwd
вместо этого'.'
иos.getcwd()
во всем, чтобы избежать нагрузки на избыточные системные вызовы.Здесь я использую рекурсивную структуру.
источник
pathlib
:filter(Path.is_file, Path().rglob('*'))
Однажды один мудрый учитель сказал мне:
Таким образом, я добавлю решение для подмножества проблемы: довольно часто мы только хотим проверить, соответствует ли файл начальной и конечной строкам, не заходя в подкаталоги. Таким образом, нам нужна функция, которая возвращает список имен файлов, например:
Если вы хотите сначала объявить две функции, это можно сделать:
Это решение может быть легко обобщено с помощью регулярных выражений (и вы можете добавить
pattern
аргумент, если вы не хотите, чтобы ваши шаблоны всегда придерживались начала или конца имени файла).источник
Использование генераторов
источник
Еще один очень читаемый вариант для Python 3.4+ использует pathlib.Path.glob:
Это проще сделать более конкретно, например, искать только исходные файлы Python, которые не являются символическими ссылками, также во всех подкаталогах:
источник
Вот моя универсальная функция для этого. Он возвращает список путей к файлам, а не имен файлов, так как я обнаружил, что это более полезно. У него есть несколько необязательных аргументов, которые делают его универсальным. Например, я часто использую его с аргументами вроде
pattern='*.txt'
илиsubfolders=True
.источник
Я предоставлю пример одного лайнера, где исходный путь и тип файла могут быть предоставлены в качестве входных данных. Код возвращает список имен файлов с расширением csv. Использование . в случае, если все файлы должны быть возвращены. Это также рекурсивно сканирует подкаталоги.
[y for x in os.walk(sourcePath) for y in glob(os.path.join(x[0], '*.csv'))]
Измените расширения файлов и исходный путь по мере необходимости.
источник
glob
, то просто используйтеglob('**/*.csv', recursive=True)
. Нет необходимости сочетать это сos.walk()
рекурсией (recursive
и**
поддерживаются начиная с Python 3.5).Для python2: pip установить rglob
источник
dircache « устарел с версии 2.6: модуль dircache был удален в Python 3.0».
источник