Як я можу перерахувати всі файли каталогу в Python і додати їх до а list
?
Як я можу перерахувати всі файли каталогу в Python і додати їх до а list
?
Відповіді:
os.listdir()
отримає все, що є в каталозі - файли та каталоги .
Якщо ви хочете лише файли, ви можете їх відфільтрувати за допомогою os.path
:
from os import listdir
from 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()
(якщо ви впевнені, що прогулянка поверне хоча б одне значення, яке воно повинно бути)
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
модуль, так як це відповідає узгодженню та розширенню.
import glob
print(glob.glob("/home/adam/*.txt"))
Він поверне список із запитуваними файлами:
['/home/adam/file1.txt', '/home/adam/file2.txt', .... ]
/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 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 glob
def 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 glob
def 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 file
elif word in f:
file.append(f)
return file
return 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 = files
for 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()
- отримуйте лише файли txt
arr_txt = [x for x in os.listdir() if x.endswith(".txt")]
print(arr_txt)
>>> ['work.txt', '3ebooks.txt']
Використовується
glob
для отримання повного шляху до файлів
Якщо мені знадобиться абсолютний шлях до файлів:
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
Використовуючи
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']
Отримайте всі імена субдірера за допомогою
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 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
Приклади:
Вих. 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 += 1
return 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 += 1
if 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
>>> ------------------------
>>> ==> Found in: `_compiti18` : 3 files
Вих. 3: Як отримати всі файли у файлі txt
Якщо ви хочете створити txt-файл із усіма назвами файлів:
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")
Як записати файл з усіма шляхами у папку типу
За допомогою цієї функції ви можете створити txt-файл, який буде мати ім'я типу файлу, який ви шукаєте (наприклад, 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()
import os
os.listdir("somedirectory")
поверне список усіх файлів і каталогів у "somedirectory".
glob.glob
os.listdir()
завжди повертає прості імена файлів (не відносні шляхи). Що glob.glob()
повертається, визначається форматом шляху вхідного шаблону.
Однорядне рішення для отримання лише списку файлів (без підкаталогів):
filenames = next(os.walk(path))[2]
або абсолютні імена:
paths = [os.path.join(path, fn) for fn in next(os.walk(path))[2]]
import os
. Здається менш лаконічним, ніж glob()
для мене.
glob()
трактує це як файл. Ваш метод трактує це як каталог.
Отримання повних шляхів до файлу з каталогу та всіх його підкаталогів
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")
print full_file_paths
який надрукує список:
['/Users/johnny/Desktop/TEST/file1.txt', '/Users/johnny/Desktop/TEST/file2.txt', '/Users/johnny/Desktop/TEST/SUBFOLDER/file3.dat']
Якщо ви хочете, ви можете відкривати та читати вміст або зосереджуватись лише на файлах із розширенням ".dat", як у коді нижче:
for f in full_file_paths:
if f.endswith(".dat"):
print f
/Users/johnny/Desktop/TEST/SUBFOLDER/file3.dat
Оскільки у версії 3.4 для цього є вбудовані ітератори, які є набагато ефективнішими, ніж os.listdir()
:
pathlib
: Нове у версії 3.4.
>>> import pathlib
>>> [p for p in pathlib.Path('.').iterdir() if p.is_file()]
Відповідно до PEP 428 , мета pathlib
бібліотеки полягає у забезпеченні простої ієрархії класів для обробки шляхів файлової системи та загальних операцій, які користувачі виконують над ними.
os.scandir()
: Нове у версії 3.5.
>>> import os
>>> [entry for entry in os.scandir('.') if entry.is_file()]
Зауважте, що він 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, який я збираюся опублікувати, походить від v3.5.4 - якщо не вказано інше). Це має наслідки, пов’язані з іншим ключовим словом у питанні: " додати їх у список ":
>>> 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 ):
E:\Work\Dev\StackOverflow\q003207219>tree /f "root_dir" Folder PATH listing for volume Work Volume serial number is 00000029 3655:6FED E:\WORK\DEV\STACKOVERFLOW\Q003207219\ROOT_DIR ¦ file0 ¦ file1 ¦ +---dir0 ¦ +---dir00 ¦ ¦ ¦ file000 ¦ ¦ ¦ ¦ ¦ +---dir000 ¦ ¦ file0000 ¦ ¦ ¦ +---dir01 ¦ ¦ file010 ¦ ¦ file011 ¦ ¦ ¦ +---dir02 ¦ +---dir020 ¦ +---dir0200 +---dir1 ¦ file10 ¦ file11 ¦ file12 ¦ +---dir2 ¦ ¦ file20 ¦ ¦ ¦ +---dir20 ¦ file200 ¦ +---dir3
[Пітон 3]: ос. listdir ( path = '.' )
Поверніть список, що містить імена записів у каталозі, заданому шляхом. Список складається у довільному порядку і не включає спеціальні записи
'.'
та'..'
...
>>> 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()
Примітки :
Вихід :
(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']
[Пітон 3]: ос. scandir ( path = '.' ) ( Python 3.5 +, резервний порт : [PyPI]: scandir )
Повертає ітератор 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
[Пітон 3]: ос. ходити ( зверху, згори = Правда, onerror = Немає, наступні посилання = Неправдиво )
Створіть імена файлів у дереві каталогів, переходячи по дереву зверху вниз або знизу вгору. Для кожного каталогу в дереві каталогів з коренем в вершині ( в тому числі і зверху сам), він дає 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
для старих версій)[Пітон 3]: глоб. glob ( ім'я шляху, *, рекурсивний = False ) ( [Python 3]: glob. iglob ( ім'я шляху, *, рекурсивний = False ) )
Поверніть можливо порожній список імен шляхів , що відповідають імені шляху , який повинен бути рядок із специфікацією шляху. ім'я контуру може бути абсолютним (подобається
/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
[Python 3]: шлях до класу. Шлях ( * сегменти шляху ) ( Python 3.4 +, резервний порт : [PyPI]: pathlib2 )
>>> 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("*") if not item.is_dir()] # Display paths (including parent) for files only ['root_dir\\file0', 'root_dir\\file1']
Примітки :
[Python 2]: dircache.listdir (шлях) ( лише для Python 2 )
os.listdir
із кешуваннямdef listdir(path):
"""List directory contents, using cache."""
try:
cached_mtime, list = cache[path]
del cache[path]
except KeyError:
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
[man7]: OPENDIR (3) / [man7]: READDIR (3) / [man7]: CLOSEDIR (3) через [Python 3]: ctypes - Бібліотека іноземних функцій для Python ( специфічна для POSIX )
ctypes - це бібліотека іноземних функцій для Python. Він надає C-сумісні типи даних та дозволяє викликати функції в DLL або спільних бібліотеках. З його допомогою можна обернути ці бібліотеки в чистий Python.
code_ctypes.py :
#!/usr/bin/env python3
import sys
from ctypes import Structure, \
c_ulonglong, c_longlong, c_ushort, c_ubyte, c_char, c_int, \
CDLL, POINTER, \
create_string_buffer, get_errno, set_errno, cast
DT_DIR = 4
DT_REG = 8
char256 = c_char * 256
class LinuxDirent64(Structure):
_fields_ = [
("d_ino", c_ulonglong),
("d_off", c_longlong),
("d_reclen", c_ushort),
("d_type", c_ubyte),
("d_name", char256),
]
LinuxDirent64Ptr = POINTER(LinuxDirent64)
libc_dll = this_process = CDLL(None, use_errno=True)
# ALWAYS set argtypes and restype for functions, otherwise it's UB!!!
opendir = libc_dll.opendir
readdir = libc_dll.readdir
closedir = libc_dll.closedir
def get_dir_content(path):
ret = [path, list(), list()]
dir_stream = opendir(create_string_buffer(path.encode()))
if (dir_stream == 0):
print("opendir returned NULL (errno: {:d})".format(get_errno()))
return ret
set_errno(0)
dirent_addr = readdir(dir_stream)
while dirent_addr:
dirent_ptr = cast(dirent_addr, LinuxDirent64Ptr)
dirent = dirent_ptr.contents
name = dirent.d_name.decode()
if dirent.d_type & DT_DIR:
if name not in (".", ".."):
ret[1].append(name)
elif dirent.d_type & DT_REG:
ret[2].append(name)
dirent_addr = readdir(dir_stream)
if get_errno():
print("readdir returned NULL (errno: {:d})".format(get_errno()))
closedir(dir_stream)
return ret
def main():
print("{:s} on {:s}\n".format(sys.version, sys.platform))
root_dir = "root_dir"
entries = get_dir_content(root_dir)
print(entries)
if __name__ == "__main__":
main()
Примітки :
os.walk
форматі. Я не намагався зробити його рекурсивним, але, виходячи з існуючого коду, це було б досить тривіальною задачеюВихід :
[cfati@cfati-ubtu16x64-0:~/Work/Dev/StackOverflow/q003207219]> ./code_ctypes.py 3.5.2 (default, Nov 12 2018, 13:43:14) [GCC 5.4.0 20160609] on linux ['root_dir', ['dir2', 'dir1', 'dir3', 'dir0'], ['file1', 'file0']]
[ActiveState.Docs]: win32file.FindFilesW ( Win конкретно)
Отримує список відповідних імен файлів за допомогою API Unicode Windows. Інтерфейс до API FindFirstFileW / FindNextFileW / Знайти функції закриття.
>>> 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 long 8 >>> [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] not in (".", "..")] # 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']
Примітки :
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 - (головний) 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 :). Якщо дерево каталогів перевищує це обмеження (я не фахівець з ФС , тому не знаю, чи це можливо), це може бути проблемою.
Треба також зазначити, що я не намагався збільшити рекурсійний ліміт, оскільки не маю досвіду в цій галузі (наскільки я можу збільшити його, перш ніж також збільшити стек на ОСрівень), але теоретично завжди буде можливість виходу з ладу, якщо глибина dir більша за найвищий можливий рекурсійний ліміт (на цій машині)
Зразки коду призначені лише для демонстраційних цілей. Це означає, що я не враховував обробку помилок (я не думаю, що немає спроб / крім / else / нарешті блокувати), тому код не є надійним (причина: тримати його якомога простіше і коротше ). Для виробництва також слід додати помилки
Використовуйте Python лише як обгортку
Найвідоміший аромат, який я знаю, - це те, що я називаю підходом адміністратора системи :
grep
/ findstr
) або форматування виводу може бути здійснено з обох сторін, але я не збираюся наполягати на цьому. Також я навмисно використовував os.system
замість subprocess.Popen
.(py35x64_test) E:\Work\Dev\StackOverflow\q003207219>"e:\Work\Dev\VEnvs\py35x64_test\Scripts\python.exe" -c "import os;os.system(\"dir /b root_dir\")" dir0 dir1 dir2 dir3 file0 file1
Взагалі цього підходу слід уникати, оскільки якщо якийсь формат виводу команд трохи відрізняється між версіями / ароматами ОС , слід також адаптувати код розбору; не кажучи вже про відмінності між локалями).
Мені дуже сподобалась відповідь adamk , пропонуючи використовувати її 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 між іменем диска і \
s, який жорстко кодується в шлях.
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.
**
працює поки ви встановили recursive = True
. Дивіться документи тут: docs.python.org/3.5/library/glob.html#glob.glob
Якщо ви шукаєте реалізацію знахідки Python , це рецепт, який я використовую досить часто:
from findtools.find_files import (find_files, Match)
# Recursively find all *.sh files in **/usr/bin**
sh_files_pattern = Match(filetype='f', name='*.sh')
found_files = find_files(path='/usr/bin', match=sh_files_pattern)
for found_file in found_files:
print found_file
Тому я зробив з нього пакет PyPI , а також є сховище GitHub . Я сподіваюся, що хтось вважає це потенційно корисним для цього коду.
Для отримання більших результатів можна використовувати 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
оператор залишає функцію, але зберігає його поточний стан, і він повертає лише ім'я запису, виявленого як файл. Все вищесказане дозволяє перевести цикл на функцію генератора.
Повертаючи список абсолютних файлових шляхів, не повторюється в підкаталогах
L = [os.path.join(os.getcwd(),f) for f in os.listdir('.') if os.path.isfile(os.path.join(os.getcwd(),f))]
os.path.abspath(f)
була б дещо дешевшою заміною os.path.join(os.getcwd(),f)
.
cwd = os.path.abspath('.')
, а потім використовувались cwd
замість нього '.'
та в os.getcwd()
усьому світі, щоб уникнути навантаження зайвих системних викликів.
import os
import os.path
def get_files(target_dir):
item_list = os.listdir(target_dir)
file_list = list()
for item in item_list:
item_dir = os.path.join(target_dir,item)
if os.path.isdir(item_dir):
file_list += get_files(item_dir)
else:
file_list.append(item_dir)
return file_list
Тут я використовую рекурсивну структуру.
Мудрий вчитель одного разу сказав мені:
Коли існує декілька встановлених способів зробити щось, жоден з них не підходить для всіх випадків.
Таким чином я додам рішення для підмножини проблеми: досить часто ми хочемо лише перевірити, чи відповідає файл початковою і кінцевою рядком, не потрапляючи в підкаталоги. Таким чином, ми хотіли б функцію, яка повертає список імен файлів, наприклад:
filenames = dir_filter('foo/baz', radical='radical', extension='.txt')
Якщо ви хочете спочатку оголосити дві функції, це можна зробити:
def file_filter(filename, radical='', extension=''):
"Check if a filename matches a radical and extension"
if not filename:
return False
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"
if not 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 import Path
folder = '/foo'
[f for f in Path(folder).glob('*') if f.is_file()]
Простіше зробити більш конкретними, наприклад, шукати лише вихідні файли Python, які не є символічними посиланнями, також у всіх підкаталогах:
[f for f in Path(folder).glob('**/*.py') if not 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).
Для python2: pip встановити rglob
import rglob
file_list=rglob.rglob("/home/base/dir/", "*")
print file_list
dircache "Застаріло з версії 2.6: Модуль dircache видалено в Python 3.0."
import dircache
list = dircache.listdir(pathname)
i = 0
check = len(list[0])
temp = []
count = len(list)
while count != 0:
if len(list[i]) != check:
temp.append(list[i-1])
check = len(list[i])
else:
i = i + 1
count = count - 1
print temp