Обход файла Python
Я пытаюсь создать функцию, которая получает имя корневого файла, затем пересекает каталог и возвращает такой список.
[["folder1",[
["subfolder1",[
"file1",
"file2"
]],
["subfolder2",[
"file3",
"file4"
]]
],"file5","file6"]
Ниже моя попытка на функции:
def traverse(rootdir):
names = []
for cdirname, dirnames, filenames in os.walk(rootdir):
# record path to all subdirectories first.
for subdirname in dirnames:
names.append([subdirname,traverse(os.path.join(cdirname, subdirname))])
# record path to all filenames.
for filename in filenames:
names.append(os.path.join(cdirname, filename))
return names
Моя проблема в том, что я всегда получаю дубликаты одних и тех же файлов / папок, записываемых с помощью этой функции, и что пути всегда отображаются относительно "rootdir", а не только имен соответствующих файлов / папок. Как отсеять дубликаты? Кроме того, как я мог сделать так, чтобы записывался не полный путь.
2 ответа
sorted
используется, чтобы сделать каталог первым. Если вы не возражаете против этого заказа, просто вернитесь names
,
def traverse(rootdir):
names = []
dirs, files = [], []
for filename in os.listdir(rootdir):
filepath = os.path.join(rootdir, filename)
if os.path.isdir(filepath):
names.append([filename, traverse(filepath)])
else:
names.append(filename)
return sorted(names, key=lambda x: (0, x[0]) if isinstance(x, list) else (1, x))
Другая версия, которая использует os.walk
:
def traverse(rootdir):
names = []
dir_to_names = {rootdir: names}
for cdirname, dirnames, filenames in os.walk(rootdir):
subnames = dir_to_names[cdirname]
for subdirname in sorted(dirnames):
subnames2 = dir_to_names[os.path.join(cdirname, subdirname)] = []
subnames.append([subdirname, subnames2])
for filename in sorted(filenames):
subnames.append(filename)
return names
Вы могли бы использовать os.walk()
получить все подкаталоги и подфайлы. Возвращает список, содержащий "тройку" с ("текущий путь", [subdirs], [subfiles]). Но это не сработало для моих нужд, поэтому я написал следующий скрипт. Надеюсь это поможет.
Что он делает, так это то, что он создает объект для каждой папки, связывая файлы и каталоги, и сортирует их по алфавиту. Я посмотрел на os.walk и как он работает, и это аналогичный подход (с isdir()). Переменная tab предназначена только для лучшего просмотра результатов.
import os
class Folder():
""" Generate a tree list from a given directory """
# List of prohibited_dirs folders on any levels
prohibited_dirs = set([])
prohibited_files = set([])
tab = 0
def __init__(self, path, folder_name):
""" path should be /home/example, folder_name: example """
self.path = path
self.folder_name = folder_name
self.sub_dirs = []
self.sub_files = []
self.__class__.tab += 1
# print self.tab
def sorter(self):
""" sorts listdir output for folders and files"""
# Sort Folders and Files
names = os.listdir(self.path)
for name in names:
if os.path.isdir(os.path.join(self.path, name)):
self.sub_dirs.append(name)
else:
self.sub_files.append(name)
def list_stuff(self):
""" sort lists, and iterate overall subfolders/files."""
# Sort alphabetically
self.sub_dirs.sort(key=str.lower)
self.sub_files.sort(key=str.lower)
# all subfolders, if is also break condition
if self.sub_dirs:
# Filter prohibited_dirs Folders
for sub_dir in self.sub_dirs:
if sub_dir in self.__class__.prohibited_dirs:
continue
print "\t" * self.tab + sub_dir
# Go deeper
deeper = Folder(os.path.join(self.path, sub_dir), sub_dir)
deeper.sorter()
deeper.list_stuff()
# Free object
del deeper
self.__class__.tab -= 1
# list all Files, if is also break condition
if self.sub_files:
for sub_file in self.sub_files:
if sub_file in self.__class__.prohibited_files:
continue
print "\t" * self.tab + sub_file
STARTDIRECTORY = "."
STARTFOLDER = "."
runner = Folder(STARTDIRECTORY, STARTFOLDER)
runner.sorter()
runner.list_stuff()