Чи є спосіб повернути список усіх підкаталогів у поточному каталозі в Python?
Я знаю, що ви можете це зробити з файлами, але мені потрібно отримати список каталогів.
Чи є спосіб повернути список усіх підкаталогів у поточному каталозі в Python?
Я знаю, що ви можете це зробити з файлами, але мені потрібно отримати список каталогів.
Відповіді:
Ви маєте на увазі безпосередні підкаталоги або кожен каталог прямо вниз по дереву?
У будь-якому випадку ви можете скористатися os.walk
для цього:
os.walk(directory)
дасть кортеж для кожного підкаталогу. Першим записом у 3-кортежі є ім'я каталогу, так
[x[0] for x in os.walk(directory)]
має надавати вам усі підкаталоги, рекурсивно.
Зауважте, що другий запис у кортежі - це список дочірніх каталогів цього запису на першій позиції, тож ви можете використовувати це замість цього, але це, ймовірно, значно не заощадить.
Однак ви можете використовувати його просто для того, щоб отримати безпосередні довідники:
next(os.walk('.'))[1]
Або подивіться інші опубліковані рішення, використовуючи os.listdir
та os.path.isdir
, в тому числі в розділі " Як отримати всі безпосередні підкаталоги в Python ".
os.walk('.').next()[1]
або os.walk('.').__next__()[1]
безпосередньо. Натомість використовуйте вбудовану функцію next()
, яка доступна як у Python 2 (див. Doc), так і в Python 3 (див. Doc) . Наприклад: next(os.walk('.'))[1]
.
os.walk('.').next()[1]
безпосередньо?
iteraror.__next__()
це внутрішній метод, і iterator.next()
використання має бути переведене на вбудований next()
відповідно до PEP-3114. Дивіться PEP-3114, який був затверджений у 2007 році.
os.walk
та os.listdir
+ os.path.isdir
рішеннями: я щойно перевірив каталог із 10000 підкаталогами (з мільйонами файлів в ієрархії нижче), і відмінності в продуктивності незначні. os.walk
: "10 петель, найкраще 3: 44,6 мс на цикл" і os.listdir
+ os.path.isdir
: "10 петель, найкраще 3: 45,1 мсек за петлю"
import os
d = '.'
[os.path.join(d, o) for o in os.listdir(d)
if os.path.isdir(os.path.join(d,o))]
os.path.join
на , o
щоб отримати повний шлях, в іншому випадку isdir(0)
завжди буде повертати брехня
os.path.join
двічі, спершу ви можете приєднатись, а потім відфільтрувати список, використовуючи os.path.isdir
: filter(os.path.isdir, [os.path.join(d, o) for o in os.listdir(d)])
Ви могли просто використовувати glob.glob
from glob import glob
glob("/path/to/directory/*/")
Не забувайте про слідування /
після *
.
/
у назвах
/
роздільником папок, зробіть це:glob(os.path.join(path_to_directory, "*", ""))
recursive=True
Набагато приємніше, ніж вище, тому що вам не потрібно кілька os.path.join (), і ви отримаєте повний шлях безпосередньо (якщо хочете), ви можете зробити це в Python 3.5 і вище.
subfolders = [ f.path for f in os.scandir(folder) if f.is_dir() ]
Це дасть повний шлях до підкаталогу. Якщо ви хочете використовувати лише ім'я підкаталогу, f.name
а не використовуватиf.path
https://docs.python.org/3/library/os.html#os.scandir
Трохи OT: Якщо вам потрібні всі підпапки рекурсивно та / або всі файли рекурсивно , перегляньте цю функцію, яка швидше, ніж os.walk
&, glob
і поверне список усіх підпапок, а також усіх файлів у цих підпапках: https://stackoverflow.com/a/59803793/2441026
Якщо ви хочете, щоб усі підпапки були рекурсивно :
def fast_scandir(dirname):
subfolders= [f.path for f in os.scandir(dirname) if f.is_dir()]
for dirname in list(subfolders):
subfolders.extend(fast_scandir(dirname))
return subfolders
Повертає список усіх підпапок з їх повними шляхами. Це знову швидше os.walk
і набагато швидше, ніж glob
.
Аналіз усіх функцій
tl; dr:
- Якщо ви хочете отримати всі негайні підкаталоги для використання папки os.scandir
.
- Якщо ви хочете отримати всі підкаталоги, навіть вкладені , скористайтесь функцією os.walk
або - трохи швидше - fast_scandir
вище.
- Ніколи не використовуйте os.walk
лише підкаталоги верхнього рівня, оскільки це може бути в сотні (!) Разів повільніше, ніж os.scandir
.
os.walk
буде основна папка. Так ви не отримаєте лише підкаталоги. Ви можете використовувати його fu.pop(0)
для видалення.Результати :
os.scandir took 1 ms. Found dirs: 439
os.walk took 463 ms. Found dirs: 441 -> it found the nested one + base folder.
glob.glob took 20 ms. Found dirs: 439
pathlib.iterdir took 18 ms. Found dirs: 439
os.listdir took 18 ms. Found dirs: 439
Тестовано на W7x64, Python 3.8.1.
# -*- coding: utf-8 -*-
# Python 3
import time
import os
from glob import glob
from pathlib import Path
directory = r"<insert_folder>"
RUNS = 1
def run_os_walk():
a = time.time_ns()
for i in range(RUNS):
fu = [x[0] for x in os.walk(directory)]
print(f"os.walk\t\t\ttook {(time.time_ns() - a) / 1000 / 1000 / RUNS:.0f} ms. Found dirs: {len(fu)}")
def run_glob():
a = time.time_ns()
for i in range(RUNS):
fu = glob(directory + "/*/")
print(f"glob.glob\t\ttook {(time.time_ns() - a) / 1000 / 1000 / RUNS:.0f} ms. Found dirs: {len(fu)}")
def run_pathlib_iterdir():
a = time.time_ns()
for i in range(RUNS):
dirname = Path(directory)
fu = [f for f in dirname.iterdir() if f.is_dir()]
print(f"pathlib.iterdir\ttook {(time.time_ns() - a) / 1000 / 1000 / RUNS:.0f} ms. Found dirs: {len(fu)}")
def run_os_listdir():
a = time.time_ns()
for i in range(RUNS):
dirname = Path(directory)
fu = [os.path.join(directory, o) for o in os.listdir(directory) if os.path.isdir(os.path.join(directory, o))]
print(f"os.listdir\t\ttook {(time.time_ns() - a) / 1000 / 1000 / RUNS:.0f} ms. Found dirs: {len(fu)}")
def run_os_scandir():
a = time.time_ns()
for i in range(RUNS):
fu = [f.path for f in os.scandir(directory) if f.is_dir()]
print(f"os.scandir\t\ttook {(time.time_ns() - a) / 1000 / 1000 / RUNS:.0f} ms.\tFound dirs: {len(fu)}")
if __name__ == '__main__':
run_os_scandir()
run_os_walk()
run_glob()
run_pathlib_iterdir()
run_os_listdir()
Якщо вам потрібне рекурсивне рішення, яке знайде всі підкаталоги у підкаталогах, використовуйте ходьбу, як було запропоновано раніше.
Якщо вам потрібні лише дочірні каталоги поточного каталогу, комбінуйте os.listdir
зos.path.isdir
Я вважаю за краще використовувати фільтр ( https://docs.python.org/2/library/functions.html#filter ), але це лише питання смаку.
d='.'
filter(lambda x: os.path.isdir(os.path.join(d, x)), os.listdir(d))
Реалізовано це за допомогою python-os-walk. ( http://www.pythonforbeginners.com/code-snippets-source-code/python-os-walk/ )
import os
print("root prints out directories only from what you specified")
print("dirs prints out sub-directories from root")
print("files prints out all files from root and directories")
print("*" * 20)
for root, dirs, files in os.walk("/var/log"):
print(root)
print(dirs)
print(files)
Ви можете отримати список підкаталогів (і файлів) в Python 2.7, використовуючи os.listdir (шлях)
import os
os.listdir(path) # list of subdirectories and files
os.listdir
перераховується вміст каталогу, включаючи файли.
print("\nWe are listing out only the directories in current directory -")
directories_in_curdir = filter(os.path.isdir, os.listdir(os.curdir))
print(directories_in_curdir)
files = filter(os.path.isfile, os.listdir(os.curdir))
print("\nThe following are the list of all files in the current directory -")
print(files)
Python 3.4 вводиться в pathlib
модулі в стандартну бібліотеку, яка забезпечує об'єктно - орієнтований підхід для обробки файлової системи шляхів:
from pathlib import Path
p = Path('./')
# List comprehension
[f for f in p.iterdir() if f.is_dir()]
# The trailing slash to glob indicated directories
# This will also include the current directory '.'
list(p.glob('**/'))
Pathlib також доступний на Python 2.7 через модуль pathlib2 на PyPi.
for f in filter(Path.is_dir, p.iterdir()):
Оскільки я натрапив на цю проблему, використовуючи шляхи Python 3.4 та Windows UNC, ось такий варіант для цього середовища:
from pathlib import WindowsPath
def SubDirPath (d):
return [f for f in d.iterdir() if f.is_dir()]
subdirs = SubDirPath(WindowsPath(r'\\file01.acme.local\home$'))
print(subdirs)
Pathlib є новим у Python 3.4 і значно спрощує роботу з шляхами під різними ОС: https://docs.python.org/3.4/library/pathlib.html
Хоча на це запитання відповіли давно. Я хочу порекомендувати використовуватиpathlib
модуль, оскільки це надійний спосіб роботи в ОС Windows і Unix.
Отже, щоб отримати всі шляхи до певного каталогу, включаючи підкаталоги:
from pathlib import Path
paths = list(Path('myhomefolder', 'folder').glob('**/*.txt'))
# all sorts of operations
file = paths[0]
file.name
file.stem
file.parent
file.suffix
тощо.
Дякую за поради, хлопці. Я зіткнувся з проблемою, коли softlinks (нескінченна рекурсія) повертався як dirs. Софтпосилання? Ми не хочемо ніяких смердючих м'яких посилань! Тому...
Це виводило просто бруди, а не софтпосилання:
>>> import os
>>> inf = os.walk('.')
>>> [x[0] for x in inf]
['.', './iamadir']
[x[0] for x in inf]
називається python, щоб я міг його переглянути?
Скопіюйте дружню пасту на ipython
:
import os
d='.'
folders = list(filter(lambda x: os.path.isdir(os.path.join(d, x)), os.listdir(d)))
Вихід від print(folders)
:
['folderA', 'folderB']
x
- це пункт зі списку, створений, os.listdir(d)
тому що listdir
поверне файли та папки, з якими він використовує filter
команду os.path.isdir
для фільтрації будь-яких файлів зі списку.
Ось як я це роблю.
import os
for x in os.listdir(os.getcwd()):
if os.path.isdir(x):
print(x)
Ось пара простих функцій на основі прикладу @Blair Conrad -
import os
def get_subdirs(dir):
"Get a list of immediate subdirectories"
return next(os.walk(dir))[1]
def get_subfiles(dir):
"Get a list of immediate subfiles"
return next(os.walk(dir))[2]
Спираючись на рішення Елі Бендерського, використовуйте наступний приклад:
import os
test_directory = <your_directory>
for child in os.listdir(test_directory):
test_path = os.path.join(test_directory, child)
if os.path.isdir(test_path):
print test_path
# Do stuff to the directory "test_path"
де <your_directory>
шлях до каталогу, який ви хочете пройти.
Здається, ця відповідь вже не існує.
directories = [ x for x in os.listdir('.') if os.path.isdir(x) ]
У мене було подібне питання недавно, і я дізнався, що найкраща відповідь для python 3.6 (як додав користувач havlock) - використовувати os.scandir
. Оскільки, здається, немає рішення для його використання, я додам своє. По-перше, нерекурсивне рішення, яке перераховує лише підкаталоги безпосередньо під кореневою каталогом.
def get_dirlist(rootdir):
dirlist = []
with os.scandir(rootdir) as rit:
for entry in rit:
if not entry.name.startswith('.') and entry.is_dir():
dirlist.append(entry.path)
dirlist.sort() # Optional, in case you want sorted directory names
return dirlist
Рекурсивна версія виглядатиме так:
def get_dirlist(rootdir):
dirlist = []
with os.scandir(rootdir) as rit:
for entry in rit:
if not entry.name.startswith('.') and entry.is_dir():
dirlist.append(entry.path)
dirlist += get_dirlist(entry.path)
dirlist.sort() # Optional, in case you want sorted directory names
return dirlist
майте на увазі, що entry.path
це абсолютний шлях до підкаталогу. Якщо вам потрібна лише назва папки, ви можете використовувати її entry.name
замість. Для отримання додаткових відомостей про entry
об'єкт зверніться до os.DirEntry .
використовувати функцію фільтра os.path.isdir
над os.listdir()
чимось подібнимfilter(os.path.isdir,[os.path.join(os.path.abspath('PATH'),p) for p in os.listdir('PATH/')])
У цьому списку будуть перелічені всі підкаталоги внизу дерева файлів.
import pathlib
def list_dir(dir):
path = pathlib.Path(dir)
dir = []
try:
for item in path.iterdir():
if item.is_dir():
dir.append(item)
dir = dir + list_dir(item)
return dir
except FileNotFoundError:
print('Invalid directory')
pathlib
є новою у версії 3.4
Функція повернення списку всіх підкаталогів у межах заданого шляху файлу. Буде проведено пошук по всьому дереву файлів.
import os
def get_sub_directory_paths(start_directory, sub_directories):
"""
This method iterates through all subdirectory paths of a given
directory to collect all directory paths.
:param start_directory: The starting directory path.
:param sub_directories: A List that all subdirectory paths will be
stored to.
:return: A List of all sub-directory paths.
"""
for item in os.listdir(start_directory):
full_path = os.path.join(start_directory, item)
if os.path.isdir(full_path):
sub_directories.append(full_path)
# Recursive call to search through all subdirectories.
get_sub_directory_paths(full_path, sub_directories)
return sub_directories
ми можемо отримати список усіх папок за допомогою os.walk ()
import os
path = os.getcwd()
pathObject = os.walk(path)
цей pathObject є об'єктом, і ми можемо отримати масив
arr = [x for x in pathObject]
arr is of type [('current directory', [array of folder in current directory], [files in current directory]),('subdirectory', [array of folder in subdirectory], [files in subdirectory]) ....]
Ми можемо отримати список усіх підкаталогів шляхом ітерації через arr і друку середнього масиву
for i in arr:
for j in i[1]:
print(j)
Це надрукує весь підкаталог.
Щоб отримати всі файли:
for i in arr:
for j in i[2]:
print(i[0] + "/" + j)
Ця функція з даним батьком directory
повторює всі її directories
рекурсивно і prints
все те, filenames
що він знаходиться всередині. Занадто корисно.
import os
def printDirectoryFiles(directory):
for filename in os.listdir(directory):
full_path=os.path.join(directory, filename)
if not os.path.isdir(full_path):
print( full_path + "\n")
def checkFolders(directory):
dir_list = next(os.walk(directory))[1]
#print(dir_list)
for dir in dir_list:
print(dir)
checkFolders(directory +"/"+ dir)
printDirectoryFiles(directory)
main_dir="C:/Users/S0082448/Desktop/carpeta1"
checkFolders(main_dir)
input("Press enter to exit ;")