Как получить все непосредственные подкаталоги в Python
Вопрос
Я пытаюсь написать простой скрипт Python, который будет копировать index.tpl в index.html во всех подкаталогах (за некоторыми исключениями).
Я увяз в попытке получить список подкаталогов.
Решение
import os
def get_immediate_subdirectories(a_dir):
return [name for name in os.listdir(a_dir)
if os.path.isdir(os.path.join(a_dir, name))]
Другие советы
Почему никто не упомянул glob
? glob
позволяет использовать расширение имен путей в стиле Unix, и я могу использовать их практически для всех задач, требующих поиска более одного пути.Это делает это очень легко:
from glob import glob
paths = glob('*/')
Обратите внимание, что glob
вернет каталог с последней косой чертой (как это сделал бы Unix), в то время как большинство path
основанные на этом решения будут опускать последнюю косую черту.
Проверять "Получение списка всех подкаталогов в текущем каталоге".
Вот версия Python 3:
import os
dir_list = next(os.walk('.'))[1]
print(dir_list)
import os, os.path
Чтобы получить (полный путь) непосредственные подкаталоги в каталоге:
def SubDirPath (d):
return filter(os.path.isdir, [os.path.join(d,f) for f in os.listdir(d)])
Чтобы получить последний (самый новый) подкаталог:
def LatestDirectory (d):
return max(SubDirPath(d), key=os.path.getmtime)
os.walk
твой друг в этой ситуации.
Прямо из документации:
walk() генерирует имена файлов в дереве каталогов, проходя по дереву сверху вниз или снизу вверх.Для каждого каталога в дереве, корнем которого является вершина каталога (включая саму вершину), он дает тройной кортеж (путь к каталогу, имена каталогов, имена файлов).
Этот метод прекрасно делает все это за один раз.
from glob import glob
subd = [s.rstrip("/") for s in glob(parent_dir+"*/")]
Использование модуля FilePath Twisted:
from twisted.python.filepath import FilePath
def subdirs(pathObj):
for subpath in pathObj.walk():
if subpath.isdir():
yield subpath
if __name__ == '__main__':
for subdir in subdirs(FilePath(".")):
print "Subdirectory:", subdir
Поскольку некоторые комментаторы спрашивают, в чем преимущества использования библиотек Twisted для этого, я выйду немного за рамки исходного вопроса.
Есть некоторая улучшенная документация в ветке, объясняющей преимущества FilePath;возможно, вам захочется это прочитать.
Более конкретно в этом примере:в отличие от версии стандартной библиотеки, эту функцию можно реализовать с помощью нет импорта.Функция «subdirs» является абсолютно универсальной, поскольку она не работает ни с чем, кроме своего аргумента.Чтобы копировать и перемещать файлы с помощью стандартной библиотеки, вам необходимо зависеть от "open
"встроенный",listdir
", возможно "isdir
" или "os.walk
" или "shutil.copy
".Может быть "os.path.join
" слишком.Не говоря уже о том, что вам нужна строка, передающая аргумент для идентификации фактического файла.Давайте посмотрим на полную реализацию, которая копирует «index.tpl» каждого каталога в «index.html»:
def copyTemplates(topdir):
for subdir in subdirs(topdir):
tpl = subdir.child("index.tpl")
if tpl.exists():
tpl.copyTo(subdir.child("index.html"))
Функция «subdirs» выше может работать на любом FilePath
-подобный предмет.Это означает, среди прочего, ZipPath
объекты.К сожалению ZipPath
сейчас доступен только для чтения, но его можно расширить для поддержки записи.
Вы также можете передавать свои собственные объекты для целей тестирования.Чтобы протестировать предложенные здесь API, использующие os.path, вам придется повозиться с импортированными именами и неявными зависимостями и вообще прибегнуть к черной магии, чтобы ваши тесты заработали.С FilePath вы делаете что-то вроде этого:
class MyFakePath:
def child(self, name):
"Return an appropriate child object"
def walk(self):
"Return an iterable of MyFakePath objects"
def exists(self):
"Return true or false, as appropriate to the test"
def isdir(self):
"Return true or false, as appropriate to the test"
...
subdirs(MyFakePath(...))
Я только что написал код для перемещения виртуальных машин VMware и в итоге использовал os.path
и shutil
для копирования файлов между подкаталогами.
def copy_client_files (file_src, file_dst):
for file in os.listdir(file_src):
print "Copying file: %s" % file
shutil.copy(os.path.join(file_src, file), os.path.join(file_dst, file))
Это не очень элегантно, но работает.
Вот один из способов:
import os
import shutil
def copy_over(path, from_name, to_name):
for path, dirname, fnames in os.walk(path):
for fname in fnames:
if fname == from_name:
shutil.copy(os.path.join(path, from_name), os.path.join(path, to_name))
copy_over('.', 'index.tpl', 'index.html')
def get_folders_in_directories_recursively(self, directory, index=0):
folder_list = list()
parent_directory = directory
for path, subdirs, _ in os.walk(directory):
if not index:
for sdirs in subdirs:
folder_path = "{}/{}".format(path, sdirs)
folder_list.append(folder_path)
elif path[len(parent_directory):].count('/') + 1 == index:
for sdirs in subdirs:
folder_path = "{}/{}".format(path, sdirs)
folder_list.append(folder_path)
return folder_list
Следующую функцию можно вызвать так:
get_folders_in_directories_recursily(directory, index=1) -> выдает список папок на первом уровне
get_folders_in_directories_recursily(directory) -> выдает все подпапки
Я должен упомянуть путь.py библиотека, которой я пользуюсь очень часто.
Получение непосредственных подкаталогов становится таким простым:
my_dir.dirs()
Полный рабочий пример:
from path import Path
my_directory = Path("path/to/my/directory")
subdirs = my_directory.dirs()
Примечание:my_directory по-прежнему можно манипулировать как строку, поскольку Path является подклассом строки, но предоставляет множество полезных методов для управления путями.
import glob
import os
def child_dirs(path):
cd = os.getcwd() # save the current working directory
os.chdir(path) # change directory
dirs = glob.glob("*/") # get all the subdirectories
os.chdir(cd) # change directory to the script original location
return dirs
А child_dirs
функция принимает путь к каталогу и возвращает список непосредственные подкаталоги в этом.
dir
|
-- dir_1
-- dir_2
child_dirs('dir') -> ['dir_1', 'dir_2']
import pathlib
def list_dir(dir):
path = pathlib.Path(dir)
dir = []
try:
for item in path.iterdir():
if item.is_dir():
dir.append(item)
return dir
except FileNotFoundError:
print('Invalid directory')