Разработчикам часто приходится иметь дело с файлами, представляющими из себя древовидную структуру: XML, JSON, YAML, всякого рода языки разметки вроде Markdown или Org-mode. Облегчая в общем и целом нашу жизнь, такие файлы имеют склонность к бесконтрольному росту, в какой-то момент из решения превращаясь в проблему.


Стандартное решение этой проблемы — разбиение на меньшие файлы. Это, конечно, работает, но не всегда удобно.


Но существует и альтернатива, о которой — ниже.


org-mode и его разметка.


Пожалуй, стоит сначала изложить мою проблему. Я использую Емакс и — как многие пользователи Емакса — для написания почти всех моих документов, заметок, рабочего дневника и списков задач использую язык разметки org-mode. Выглядит документ в этой разметке примерно следующим образом:


... простой пример файла из репозитория ...
> cat tests/simple.org
document section
* headline 1
headline section 1
** inner headline 1
some inner section 1
some inner section 1-2
** inner headline 2
inner section 2
** inner headline 3
*** inner inner headline 1
* headline 2
section text 2

Один мой документ разросся до нескольких сотен подзаголовков различной глубины вложенности, и по всем этим заголовкам я регулярно прохаживаюсь скриптами в поисках разной информации. Разбирать документ на несколько файлов не хотелось, т.к. синхронизировать между машинами или каким-либо скриптом обрабатывать один файл все же легче. Но и жить так дальше было решительно невозможно.


И тогда мне в голову пришло, что было бы здорово ходить по моему файлу как по директориям, при помощи, скажем, стандартных в Юниксах cd headline1 или cd .., ls -l и cat section.


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


Конечно, писать полноценную файловую систему для Линукса — дело долгое, неблагодарное и уж точно не стоит оно того в такого рода редких случаях.


FUSE


Впрочем, в наши дни уже никто так и не делает, то есть с тех пор как лет десять назад в Линукс был включен модуль FUSE, позволяющий делать файловые системы в виде обыкновенного пользовательского процесса, на который из ядра маршрутизируются все связанные со смонтированной файловой системой /системные вызовы.


С помощью FUSE было написано множество самых разных файловых систем, от игрушечных ФС, монтирующих, например, статьи с Википедии, до вполне серьезных частей современных Линуксов вроде того же Gnome. Таким образом, FUSE стал обязательным элементом популярных дистрибутивов.


Еще приятней работу с FUSE делает тот факт, что в наши дни доступны совсем уж тривиальные в использовании обертки на высокоуровневых языках вроде Python, Ruby, Java и многих других, т.е. собственную файловую систему можно сделать буквально за два-три часа.


fusepy


Конкретно на Питоне оберток вокруг libfuse (клиентской части FUSE) даже несколько, но больше всего мне понравился проект fusepy: код проекта очень простой и понятный, кроме примеров на Гитхабе и исходного кода мне так ничего и не понадобилось.


Файловая система на базе fusepy сводится к переопределению методов класса fuse.Operations, каждый из которых соответствует какому-либо системному вызову.


Для непереопределенных системных вызовов есть либо разумное поведение по умолчанию, либо стандартная ошибка.


Orgfuse


Собственно, конкретный формат файла, который хочется представить в виде дерева директорий и файлов, не так важен. В случае с разметкой org-mode мне не понравился ни один из доступных парсеров для Питона, и я просто написал собственный. Парсер проходит по указанному файлу, создавая дерево, отражающее структуру документа.


Дерево разбора (parse tree) файла разметки дальше преобразуется в другое дерево, отражающее файлы и директории, которые будет видеть пользователь файловой системы.


Чтобы работать с последним деревом было достаточно реализовать четыре системных вызовов (open, read, readdir, getattr), каждый из которых занимал буквально несколько строк кода на Питоне:


class FuseOperations(Operations):

    def __init__(self, tree):
        self.tree = tree
        self.fd = 0

    def open(self, path, flags):
        self.fd += 1
        return self.fd

    def read(self, path, size, offset, fh):
        node = self.tree.find_path(path)
        if node is None:
            raise FuseOSError(EIO)
        return node.content[offset:offset + size]

    def readdir(self, path, fh):
        node = self.tree.find_path(path)
        if node is None:
            raise FuseOSError(EROFS)
        return ['.', '..'] + [child for child in node.children]

    def getattr(self, path, fh=None):
        node = self.tree.find_path(path)
        if node is None:
            raise FuseOSError(ENOENT)
        return node.get_attrs()

Итоговый скрипт работает примерно следующим образом:


... монтируем файл как файловую систему ...
> mkdir mount
> python orgfuse.py tests/simple.org mount/
... открываем другой терминал и наслаждаемся ...
> tree mount
mount/
+-- headline 1
¦   +-- inner headline 1
¦   ¦   L-- section
¦   +-- inner headline 2
¦   ¦   L-- section
¦   +-- inner headline 3
¦   ¦   L-- inner inner headline 1
¦   L-- section
+-- headline 2
¦   L-- section
L-- section

6 directories, 5 files

Все это чудо занимает порядка двух сотен строк или 3-4 часа моей ленивой вечерней работы, с моей маленькой задачей справляется замечательно.


Инструкции по установке и код, как водится, можно найти Github.


Если кому интересно преращение прототипа во что-то удобоваримое, с возможностью редактирования файлов и поддержкой большего количества форматов — буду рад пообщаться.

Поделиться с друзьями
-->

Комментарии (50)


  1. KlimovDm
    19.11.2016 18:17
    +5

    Интересное решение, очень. Мне совсем недавно нужно было нечто похожее (как сейчас стало понятно), но не додумался… Спасибо, надо поэкспериментировать…


  1. MonkAlex
    19.11.2016 20:28
    -8

    Читал по диагонали, не понял, какую проблему решали то? Что плохого в древовидном json например?


    1. MonkAlex
      20.11.2016 19:36
      -1

      Спасибо за минуса, товарищи. Я перечитал статью. Всё равно не понял, ибо человек сначала придумал себе проблемы, потом их героически решил.


      1. KlimovDm
        20.11.2016 21:01
        +1

        Мне кажется, что вы просто не поняли о чем речь. Поэтому и не можете оценить элегантность решения.


        1. MonkAlex
          21.11.2016 10:50

          Я не понял в чем проблема хранить файлово то, к чему хочется обращаться как к файлам.


          1. VlK
            21.11.2016 13:07

            Может быть, я не достаточно аккуратно изложил проблему.

            Есть единый сложный файл, который в принципе кормится одной системе как единый файл, и с этим трудно что-то сделать. С другой стороны, хочется с некоторыми ветками дерева этого файла работать прямо из консоли, простыми скриптами.

            Вот и все дела.


            1. MonkAlex
              21.11.2016 14:13

              Этот файл вами и создан, как я понимаю. В чём проблема создать N файлов так как вам хочется иерархически?


              1. VlK
                21.11.2016 14:45

                Вы не читаете то, что я уже написал: файл нужен как единое целое в другом месте.

                Более того, этот скрипт и делает это самое «создать N файлов иерархически» совершенно автоматически.


                1. MonkAlex
                  21.11.2016 14:57

                  синхронизировать между машинами или каким-либо скриптом обрабатывать один файл все же легче
                  Но синхронизация как раз таки файловая же везде нынче. Файлы — проще. Синхронизация отдельных файлов — быстрее.

                  А по скриптам — так вообще не понял, наоборот же, проще каждому скрипту рассказать в какой файл он должен писать, чем объяснить структуру единого файла.

                  Привязка к одному файлу у вас идеалогическая, имхо, а не техническая.


                  1. VlK
                    21.11.2016 16:34

                    А по скриптам — так вообще не понял, наоборот же, проще каждому скрипту рассказать в какой файл он должен писать, чем объяснить структуру единого файла.


                    Именно про это я и говорю. Писать легче в отдельные файлы. Поэтому большой конфиг превращается в файлы.

                    Но этот же конфиг мне нужен как один штука, потому что только один штука на входе понимает та система, которая его переваривает. Вот и все дела :-)


                    1. MonkAlex
                      21.11.2016 16:49

                      Ааа, просто есть ещё какая то система. Вот про это в шапке что-то не уловил и не понял в итоге зачем. Всё, тогда понятно, спасибо.


  1. Rampages
    19.11.2016 21:11
    +1

    \<offtop\>
    У меня другая проблема – не могу придумать правильную структуру каталогов (классификацию файлов), т.е. есть много файлов, которые можно отнести сразу в несколько папок, городить ссылки из одной папки в другую как-то мягко говоря не правильно.
    Такое ощущение, что нужно писать базу данных с ссылками на локальные файлы и задавать им классификацию (категории, метки, темы и т.п.), далее к этому уже интерфейс какой-то… Каталогизатор какой-то получается.
    \</offtop\>


    1. Evengard
      19.11.2016 21:25
      +2

      Вам тегировать файлы нужно. Посмотрите в сторону чего нить вроде https://www.tagsistant.net/


    1. roach1967
      20.11.2016 01:07

      Есть-же такая штука — жёсткая ссылка.
      Вот только как реализовать.:( С питоном я никак от слова совсем…


      1. lightman
        20.11.2016 11:51

      1. Z-r
        20.11.2016 19:34
        +1

        Стесняюсь спросить, а при чем здесь Питон?


    1. Am0ralist
      20.11.2016 01:30
      +2

      Такая же проблема.
      Уже пару лет думаю над тем, чтобы сесть и попробовать написать свой файловый менеджер:
      — иерархические теги, возможность задать файлу неограниченное количество тегов
      — поиск по тегам с помощью диаграмм Венна (для наглядности)
      — отслеживанием изменений фс в заданных папках (добавление и удаление файлов, переименование старых, перемещение в отслеживаемые папки — папок с файлами)
      — всплывающее окно с предложением назначить теги новым файлам в отслеживаемых папках
      — отслеживание полных дубликатов
      — и, видимо, хранить всю эту инфу в бд какой-нибудь.

      Просто когда количество схем оригами начинает переваливать за десяток гигабайт начинаются проблемы с поиском какой-нибудь там схемы хамелеона Итагаки Ючи, которая была в каком-то из 150 номеров Tanteidan Magazine. Причем каждый сборник — это пдфка целая, в которой десяток разных схем, так что в имя нельзя все занести…


    1. Sirikid
      20.11.2016 15:24

      Вы не один, лично знаю ещё 3-ех человек которые задавались подобным вопросом. Предлагаемые варианты решения:
      1. жесткие ссылки (пробовал, имхо не очень удобно, запутывался в количестве ссылок на файл)
      2. дерево катологов (пробовал, нереально создать такое для всех своих файлов)
      3. файловый менеджер с БД с информацией о файлах (такой создает Konachan700, но только для картинок afaik)
      4. метаинформация
      — в файле по типу rarjpeg
      — в расширенных атрибутах
      — в специализированной фс

      Вообще было бы неплохо собраться в кучку и сочинить что-нибудь, цели очень похожие.
      cc: Am0ralist


      1. Sirikid
        20.11.2016 16:25

        Немного перефразирую, хранить метаинформацию хочется в любом случае, можно делать это в
        — файле
        — пути (папки = теги + жесткие ссылки)
        — БД файлового менеджера
        — расширенных атрибутах фс


        1. Am0ralist
          20.11.2016 18:06

          1) Если хранить в доп.файле для каждого из тегируемых файлов, то копировать надо все их, что проблематично, когда ты хочешь поделиться одним файлом из папки.
          А для каждого поиска вначале найти все доп.файлы, а потом уже анализировать из содержимое.
          Мне кажется, больно много накладных расходов, если только не кешировать это все еще куда и не копировать опять же спец.инструментом, а тогда опять же получается БД + файловый менеджер.

          2) в пути и жестких ссылках хранить большое количество тегов (особенно иерархических, особенно, когда тег может быть включен в разные иерархические ветки) + легко это взять и скопировать друзьям?

          3) в этом случае копировать можно кусок базы и делать это средствами самого файлового менеджера (то есть копировать файлы через него), при этом еще выбрать какие теги копировать, а какие нет. Причем привязку делать к имени и хешу файла, например, для того, чтоб на другом компьютере такой же файловый менеджер позволил эту информацию легко подцепить, даже если изменились пути, имя без содержимого или содержимое без имени.

          4) Было бы идеально, но желательно тогда, чтоб все популярные ФС это поддерживали, для легкого копирования между компьютерами…

          Возможно где-то ошибаюсь? Просто в свое время потратил много времени на анализ хотелок и возможностей разных программ, а в итоге найденная программа, в которой работала хотя бы часть желалок — работала только под win32 из-за того, что служба не была скомпилирована под x64, а кросплатформерных приложений вообще не нашел.
          Особенно порадовала прога с а-ля облаком тегов, в котором облако не масштабировалось и не прокручивалось, в итоге после 30 тегов программу просто выкинул.


          1. Sirikid
            21.11.2016 06:41

            1) Не в доп. файле, а в том же самом.
            4) Мне кажется это оно: https://en.wikipedia.org/wiki/Extended_file_attributes


            1. Am0ralist
              21.11.2016 09:25

              1) Если в том же самом, то есть изменяем файл — то не все форматы поддерживают метаданные. Как поведут себя файлы произвольного формата — мне сложно сказать. Плюс проблема дубликатов возникает, когда у тебя хранится уже измененный файл, а ты добавляешь исходный с другим названием, например.

              4) В windows для этого используют по сути альтернативные файловые потоки особо извращенным способом. Проблема в том, что эти расширенные атрибуты молча не копируются на тот же Fat32 (привет флешкам и SD-картам), а вот альтернативные потоки хотя бы ошибочку выдадут. Плюс доступ к ним через Жо… веселое API.
              При этом сами по себе эти альтернативные потоки позволяют к 1 кб файлику прицепить хоть 100 гб, которые напрямую не увидишь — удобно, что бы прятать (порно) любой файлик от любопытных взглядов. Ну, то есть я знаю одну программу, которая точно позволяла легко смотреть файловые потоки, да.

              С учетом, что я это планировал делать для удобного обмена файлами между людьми, которые слабо понимают в IT (самому перелопатить все да потом поддерживать — нереально)…


              1. av0000
                22.11.2016 22:14

                С учетом, что я это планировал делать для удобного обмена файлами между людьми, которые слабо понимают в IT (самому перелопатить все да потом поддерживать — нереально)…


                Рискну «влезть» — из серии «хорошо забылое старое».

                Были на заре такие файловые менеджеры — Volkov Commander и DOS Navigator. Кто у кого тогда «спёр» идею, сейчас уже не угадаешь, но умели они, как и FIDO-шный софт править файлы-компаньоны (как минимум — files.bbs и descript.ion) — в частности при копировании с места на место.

                По сути — та же БД со спец. инструментом, но вполне доступным, встроенным в файловый менеджер (ну, да, какое-то расширение для GUI-евых «проводнико» напрашивается) и годным для людей, далеких от IT.

                Некоторые мои знакомые архивариусы (из совсем не молодых ещё по тем временам) с огромным удовольствием пользовались такой возможностью и этого им вполне хватало (в купе с ручной правкой/написанием содержимого files.bbs — ну не было тогда готовых отдельных редакторов)


                1. Am0ralist
                  22.11.2016 22:58

                  А почему «рискну»?
                  Тут любые варианты интересны в плане того, что даже посмотреть кто как делал.
                  Да и вдруг всплывет что-нибудь уже существующее а-ля tag2find, который под 64 не работает к сожалению, но хотя бы часть возможностей требуемых поддерживал.

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


                  1. av0000
                    23.11.2016 08:45

                    А почему «рискну»?
                    Тут любые варианты интересны

                    Это, скорее, хабра-призказка ;)
                    Для себя искал и порывался написать «тегировалку» фото коллекции — после ухода с винды, где этого добра валом, но как-то «отпустило» или стало лень

                    А на предмет вариантов — из той же серии: берём графические редакторы или даже более-менее старые фотоаппараты с поддержкой RAW — там к каждому файлу, который «неизменен», прикладывается мелкий (.thm, .xmp и т.п.) со всякими разностями — от режима «проявки» RAW, до истории изменений и тегов.

                    Из готового — тот же shotwell под линукс — умеет коллекции тегов с сортировкой/выборкой. По отдельной команде записывает теги в файлы, если поддержка, как у jpeg. Далее такой файл переносится на другой комп, а там теги вычитываются и кладутся в локальную базу. Вроде бы оно даже умело интегрироваться с «родными» проводниками для Gnome/KDE a'la дополнительные атрибуты файлов.


    1. Z-r
      20.11.2016 16:02

      есть много файлов, которые можно отнести сразу в несколько папок

      Значит пора отказываться от концепции «папок» в пользу концепции «меток».


      городить ссылки из одной папки в другую как-то мягко говоря не правильно

      Правильно. Все каталоги у нас теперь не «папки», а «метки», и все ссылки на один и тот же документ должны быть равноправны, то есть есть это должны быть жесткие ссылки, а не символьные.


      Единственная проблема — ext[234], в отличие от, например, NTFS, не хранит обратных ссылок с инодов на файлы, а поэтому, если стороннего индекса нет, то для удаления документа, если такое вдруг понадобится, придется делать полный перебор:


      $ find ~/ -xdev -samefile useless-file.org -delete

      Для резервирования такой ФС, rsync(1)’у надо будет додать ключ -H.


      В остальном — никаких особенностей.


      1. Am0ralist
        20.11.2016 17:48

        а копировать такое друзьям как?
        Ну вот хочу часть своей базы схем поделиться с кем-то, вместе со всеми «тегами» конкретных файлов, кроме личных оценок (оценок сложности схемы и того, нравится ли мне модель, например).
        Как это будет происходить в таком случае?


        1. Z-r
          20.11.2016 18:08

          хочу часть[ю] своей базы схем поделиться с кем-то

          Если часть — это такие-то метки со всем, что под ними лежит, то просто — тем же rsync -aH.


          вместе со всеми «тегами» конкретных файлов

          А вот есть так, то есть если часть — это отдельные документы, размазанные по всему дереву меток, то опять же — только полным перебором. Увы, не хранит ext обратные ссылки.


          Мне это ни разу не было не нужно, так что костыля я не написал, но понятно, что он элементарный.


          1. Z-r
            20.11.2016 19:46
            +1

            Мне это ни разу не было не нужно, так что костыля я не написал, но понятно, что он элементарный.

            А вообще, что уж там, давайте напишем:


            #!/bin/bash
            
            # config
            TREE_ROOT="$HOME/origami"
            
            SCRIPTNAME='amoralist-cp'
            USAGE=$"Usage: $SCRIPTNAME <source>... <dest>"
            
            (($# >= 2)) || { printf >&2 '%s\n' "$USAGE"; exit 0; }
            
            dest="${!#}"
            
            for ((i = 1; i <= $# - 1; i++)); do
                if [[ -d ${!i} ]]; then
                    printf >&2 '%s\n' $"${!i} is directory; ignored"
                else
                    find_argv+=('-samefile' "${!i}" '-or')
                fi
            done
            unset find_argv[-1]
            
            find "$TREE_ROOT" -xdev "${find_argv[@]}" -printf '%P\n'     | rsync --archive --hard-links --files-from - "$TREE_ROOT" "$dest"


      1. Sirikid
        23.11.2016 09:01

        А есть файловые системы которые хранят обрытные ссылки?


        1. Z-r
          24.11.2016 14:18

          Ну, одну я уже упомянул — NTFS. :-)

          Есть ли *стандартные* файловые системы, что хранят обратные ссылки с инодов на файлы, вы хотите спросить? А вот не знаю — интересовался этим весьма поверхностно.


          1. Sirikid
            24.11.2016 14:35

            меняем *стандартные* на *можно адекватно использовать с Linux или FreeBSD* и получится то что я хотел спросить :^)


  1. ser-mk
    20.11.2016 01:07

    отличное решение!
    до этого я только предполагал такую реализацию через плагин VFS для Midnight Commander. Там мне показалось не так удобно как с fusepy))


  1. Str3lok
    20.11.2016 01:07
    +1

    Парсинг все равно происходит и все запросы парсера файловой системы пройдут через ядро. Гораздо быстрее работать с единым файлом напрямую. Но как задача для знакомства с fusepy — годится.


    1. VlK
      20.11.2016 01:13

      Я вроде не написал, что данное решение мне срочно надо использовать для обработки миллионов запросов в секунду…

      Для скорости я бы писал не на Питоне, и обрабатывал системные вызовы бы не в один поток, и т.д. и т.п. В конце концов можно написать модуль файловой системы для ядра.

      И если вам действительно надо условный миллион раз за условную же наносекунду читать конфиг, то, быть может, вы что-то делалете не то..?


      1. Str3lok
        20.11.2016 10:20
        -2

        Конечно, я часто делаю что-то не так. А кто не ошибается? Но работа приучила меня проектировать так, чтобы задача решалась с наименьшим выделением тепла. Это нравится экологам и в итоге не приносит неприятных сюрпризов с ростом обрабатываемой информации.
        Вы же понимаете, что на один шаг парсера файловой системы будет 4(!) переключения из юзерспейса в ядро и обратно?
        Здесь гораздо интереснее будет инвертировать задачу: раскидать много малых файлов по реальной файловой системе и предоставить один виртуальный для КЭШированного доступа.
        В итоге и применять можно оба подхода и системные вызовы экономятся.


        1. VlK
          20.11.2016 16:12
          +1

          Ну да, отчасти вы, конечно, правы. С другой стороны, у меня было несколько часов на все про все, и тут уж не до спасения планеты. :-)

          Ваша идея тоже звучит интересно, признаться, но это ваша идея и ваш интерес, не могу ж я их взять и украсть :-)


  1. maxzhurkin
    20.11.2016 01:21

    А что за ад из переносов строки в тексте статьи?


    1. VlK
      20.11.2016 01:22

      Хабр не вполне корректно обрабатывает переносы. Спасибо, исправил.


  1. Rigidus
    20.11.2016 01:30

    Редактирование определенно необходимо. Я бы даже очень был рад полному интерфейсу


  1. bitterman
    20.11.2016 14:27
    +1

    Похожую тему рассказывали про ОС Plan9. Её постоянным пользователем является (как оказалось) некий ВУЗ Барселоны, занимающийся переводами текстов. Им очень нравится, что в основе ОС многоязыковость и при этом очень легко создавать свои специализированные файловые системы. Вот они дожились до того, чтобы переводить тексты при помощи таких файловых систем — документ делится на разделы, разделы переводят разные люди — для ускорения. И вот здесь фишки Plan9 им оказываются очень впору. Если интересно, можно раскопать, как у них это происходило — у автора статьи очень похожий — и правильный! — взгляд на схожую проблему. Круто решать такие задачи :-)


    1. VlK
      20.11.2016 16:08

      Да, мне очень нравится этот подход, когда все — файлы, и поэтому все инструменты являются универсальными.

      собственно говоря, FUSE, Sysfs и procfs в Линуксах появились по мотивам разработок Plan9


  1. delvin-fil
    20.11.2016 16:03

    А чем ZIM не подошел(не имею ввиду портирования файлов в него)?
    Глянув на его код можно было и немного переиначить, а потом «натравить» на свои.


    1. VlK
      20.11.2016 16:05

      ZIM, который формат файла? А при чем здесь вообще конкретный формат файла?

      Статья ведь про то, что файлы с иерархией можно легко монтировать как файловую систему, и тогда для работы с содержимым можно пользоваться любыми привычными инструментами.


      1. delvin-fil
        21.11.2016 08:29

        ZIM — программа, домашнее wiki. На питоне.

        файлы с иерархией можно легко монтировать как файловую систему

        Я про это и сказал, что вместо того, чтобы разрабатывать с нуля, можно было посмотреть, как программа делает из одного файла древовидную структуру. А потом, на том же питоне(zim на питоне), написать код под персональные нужды.
        Ссылка: https://ru.wikipedia.org/wiki/Zim


        1. VlK
          21.11.2016 10:53

          У меня нет проблемы сделать из файла древовидную структуру :-) Такие вещи называются парсерами, и с этим уже давно ни у кого нет проблем.

          У меня проблема — представление одной древовидной структуры в виде другой, файловой.


          1. delvin-fil
            21.11.2016 11:04

            Эммм… А я разве о другом? Там, в проге есть разделение(типа офисовского «совместного использования файла»(зависит от версии)). Как прога предоставляет ее по сети? Разве не файловой системой?
            Тут, мне кажется, спор излишен, ибо я говорил о «посмотреть код программы», а вы так и становились на файловой системе.


            1. VlK
              21.11.2016 16:44

              Т.е. вы предлагаете адаптировать программу, визуально отображающую файлы с вики-подобной разметкой в виде дерева..?

              Я, вероятно, не совсем вас сразу понял.


              1. delvin-fil
                22.11.2016 06:59

                Не совсем. Просто посмотреть код и взять нужное для себя.


                1. VlK
                  22.11.2016 13:33

                  А что вообще мне там может быть нужно, в этом коде? Т.е., зачем мне разбираться в софтине на тысячи строк кода, когда все решение занимает меньше двух сотен строк?

                  Опять же, какое отношение софт для просмотра файлов с вики-подобным синтаксисом имеет к скриптам, работающим с файловой системой?