Как скопировать файловое дерево в виде списка Python? - PullRequest
0 голосов
/ 26 апреля 2018

Мне нужно скопировать функциональность дерева каталогов файлов в виде списка.Я должен иметь возможность искать конкретные "документы" через "папки".Все из которых могут содержать повторяющиеся имена на других глубинах.Я также должен иметь возможность динамически добавлять новые файлы и папки во время выполнения.Например, дерево файлов выглядит следующим образом:

MyFiles
    Important
        doc1
        doc2
    LessImportant
        doc3
        doc4
    LowPriority
        Important
            doc1
        LessImportant
            doc4

Если я использую вложенные списки, приведенное выше дерево в конечном итоге будет выглядеть так:

[MyFiles,[Important,[doc1,doc2],LessImportant,[doc3,doc4],LowPriority, 
[Important,[doc1],LessImportant,[doc4]]]]

И тогда мне придется запуститьперебирает все гнезда для поиска вещей и использования .append для добавления новых «папок» или «документов».

Есть ли лучший / более эффективный способ, чем вложенные списки?

Ответы [ 3 ]

0 голосов
/ 26 апреля 2018

Подход ООП

На первый взгляд у вас может сложиться впечатление: «Нет, это слишком много строк кода», но у него есть некоторые большие преимущества (например, вы более гибки).

Класс / Базовая конструкция

class FileOrFolder:

    def __init__(self, name, children=None):
        self.name = name
        self.children = children if children else []

    def search_for(self, f_name):
        global hits  # defined later on

        for child in self.children:

            if child.name == f_name:
                hits.append(child.name)

            if child.children:
                child.search_for(f_name)

Воссоздание дерева файлов

TREE = FileOrFolder("MyFiles", [
    FileOrFolder("Important", [
        FileOrFolder("doc1"),
        FileOrFolder("doc2")
    ]),
    FileOrFolder("LessImportant", [
        FileOrFolder("doc3"),
        FileOrFolder("doc4")
    ]),
    FileOrFolder("LowPriority", [
        FileOrFolder("Important", [
            FileOrFolder("doc1")
        ]),
        FileOrFolder("LessImportant", [
            FileOrFolder("doc4")
        ])
    ])
])

Application & Ouput

>>> hits = []
>>> TREE.search_for("doc4")
>>> print(hits)

['doc4', 'doc4']

ПРИМЕЧАНИЕ: Однако я не знаю, является ли ваша общая цель - просто создать дерево файлов вручную или автоматически перебрать существующее и реальное дерево и "скопировать его".В случае, если это последнее, вам нужно будет внести небольшие изменения.

0 голосов
/ 27 апреля 2018

Использование ElementTree предоставляет функции поиска и итерации.

import os
import xml.etree.ElementTree as ET

def ls(p):
    if os.path.isdir(p):
        node = ET.Element(os.path.basename(p), type='dir')
        node.extend([ls(os.path.join(p, f)) for f in os.listdir(p)])
    else:
        node = ET.Element(os.path.basename(p), type='file')
    return node

Затем проверьте это, записав в XML-формате, что довольно просто из ElementTree:

root = ET.ElementTree(ls(r"C:\test\Myfiles"))

from xml.dom import minidom
def pp(tree):
    print ''.join(minidom.parseString(ET.tostring(tree.getroot())).toprettyxml(indent='  ').splitlines(True)[1:])

pp(root)

Дает

<Myfiles type="dir">
  <Important type="dir">
    <doc1 type="file"/>
    <doc2 type="file"/>
  </Important>
  <LessImportant type="dir">
    <doc1 type="file"/>
    <doc2 type="file"/>
  </LessImportant>
  <LowPriority type="dir">
    <Important type="dir">
      <doc1 type="file"/>
    </Important>
    <LessImportant type="dir">
      <doc4 type="file"/>
    </LessImportant>
  </LowPriority>
</Myfiles>

Вы можете поиграть, чтобы решить, должен ли dir или file быть тегом элемента или атрибутом.

0 голосов
/ 26 апреля 2018

А как насчет такой структуры, использующей тип данных dict:

{"ID": 0, "Type": 'Folder', "Name": 'MyFiles', "Subdirectories": [1, 2, 3]}
{"ID": 1, "Type": 'Folder', "Name": 'Important', "Subdirectories": []}
{"ID": 2, "Type": 'Folder', "Name": 'LessImportant', "Subdirectories": []}
{"ID": 3, "Type": 'Folder', "Name": 'LowPriority', "Subdirectories": [4, 5]}
{"ID": 4, "Type": 'Folder', "Name": 'Important', "Subdirectories": []}
{"ID": 5, "Type": 'Folder', "Name": 'LessImmportant', "Subdirectories": []}

{"ID": 0, "Type": 'File', "Name": 'doc1', 'ParentDirectory': 1}
{"ID": 1, "Type": 'File', "Name": 'doc2', 'ParentDirectory': 1}
{"ID": 2, "Type": 'File', "Name": 'doc3', 'ParentDirectory': 2}
{"ID": 3, "Type": 'File', "Name": 'doc4', 'ParentDirectory': 2}
{"ID": 4, "Type": 'File', "Name": 'doc1', 'ParentDirectory': 4}
{"ID": 5, "Type": 'File', "Name": 'doc4', 'ParentDirectory': 5}

, который позволит вам анализировать данные рекурсивным способом.Здесь файлы нумеруются отдельно от папок.Каждый файл имеет запись Parentdirectory, которая является текущим каталогом, в котором находится файл. Папки имеют список подкаталогов, и все элементы связаны через поле данных ID.

...