Я пытаюсь написать простой Python script, который скопирует index.tpl в index.html во всех подкаталогах (за некоторыми исключениями).
Я завязался, пытаясь получить список подкаталогов.
Я пытаюсь написать простой Python script, который скопирует 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() генерирует имена файлов в дереве каталогов, идя по дереву сверху вниз или снизу вверх. Для каждого каталога в дереве, укорененном в верхней части каталога (включая сам верх), он дает 3-кортеж (dirpath, dirnames, filenames).
Этот метод прекрасно делает все за один раз.
from glob import glob
subd = [s.rstrip("/") for s in glob(parent_dir+"*/")]
Используя Twisted FilePath модуль:
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
-like. Что означает, среди прочего, объекты ZipPath
. К сожалению, 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_recursively (directory, index = 1) → выдает список папок первого уровня
get_folders_in_directories_recursively (каталог) → дает все подпапки
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']
Я должен упомянуть библиотеку path.py, которую я использую очень часто.
Извлечение непосредственных подкаталогов становится таким простым:
my_dir.dirs()
Полный рабочий пример:
from path import Path
my_directory = Path("path/to/my/directory")
subdirs = my_directory.dirs()
NB: my_directory все еще можно манипулировать как строку, поскольку 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)
return dir
except FileNotFoundError:
print('Invalid directory')