Есть ли способ вернуть список всех подкаталогов в текущем каталоге в 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 (см. Документ), так и в Python 3 (см. Документ) . Например: 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
: я только что протестировал каталог с 10 000 подкаталогов (с миллионами файлов в иерархии ниже), и различия в производительности незначительны. 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()
Если вам нужно рекурсивное решение, которое найдет все подкаталоги в подкаталогах, используйте walk, как предлагалось ранее.
Если вам нужны только дочерние каталоги текущего каталога, объедините 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
и т.п.
Спасибо за советы ребята. Я столкнулся с проблемой с программными ссылками (бесконечная рекурсия), возвращаемыми как dirs. Softlinks? Мы не хотим никаких вонючих мягких ссылок! Так...
Это делает только каталоги, а не программные ссылки:
>>> 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
вместо этого. Обратитесь к os.DirEntry для получения дополнительной информации об entry
объекте.
использовать функцию фильтра 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 ;")