Обход файла 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()
Другие вопросы по тегам