Проблема по тегу "Файловая система" - PullRequest
5 голосов
/ 18 мая 2009

По рекреационным причинам я написал класс PHP, который классифицирует файлы с тегами, а не иерархически, теги хранятся в самом имени файла в виде + tag1 + tag2 + tagN + MD5.EXTENSION, и поэтому я застрял с пределом символов (255), установленным FS / OS. Вот этот класс:

<?php

class TagFS
{
    public $FS = null;

    function __construct($FS)
    {
        if (is_dir($FS) === true)
        {
            $this->FS = $this->Path($FS);
        }
    }

    function Add($path, $tag)
    {
        if (is_dir($path) === true)
        {
            $files = array_slice(scandir($path), 2);

            foreach ($files as $file)
            {
                $this->Add($this->Path($path) . $file, $tag);
            }

            return true;
        }

        else if (is_file($path) === true)
        {
            $file = md5_file($path);

            if (is_file($this->FS . $file) === false)
            {
                if (copy($path, $this->FS . $file) === false)
                {
                    return false;
                }
            }

            return $this->Link($this->FS . $file, $this->FS . '+' . $this->Tag($tag) . '+' . $file . '.' . strtolower(pathinfo($path, PATHINFO_EXTENSION)));
        }

        return false;
    }

    function Get($tag)
    {
        return glob($this->FS . '*+' . str_replace('+', '{+,+*+}', $this->Tag($tag)) . '+*', GLOB_BRACE);
    }

    function Link($source, $destination)
    {
        if (is_file($source) === true)
        {
            if (function_exists('link') === true)
            {
                return link($source, $destination);
            }

            if (is_file($destination) === false)
            {
                exec('fsutil hardlink create "' . $destination . '" "' . $source . '"');

                if (is_file($destination) === true)
                {
                    return true;
                }
            }
        }

        return false;
    }

    function Path($path)
    {
        if (file_exists($path) === true)
        {
            $path = str_replace('\\', '/', realpath($path));

            if ((is_dir($path) === true) && ($path[strlen($path) - 1] != '/'))
            {
                $path .= '/';
            }

            return $path;
        }

        return false;
    }

    function Tag($string)
    {
        /*
        TODO:
        Remove (on Windows):            . \ / : * ? " < > |
        Remove (on *nix):               . /
        Remove (on TagFS):              + * { }
        Remove (on TagFS - Possibly!)   -
        Max Chars (in Windows)          255
        Max Char (in *nix)              255
        */

        $result = array_filter(array_unique(explode(' ', $string)));

        if (empty($result) === false)
        {
            if (natcasesort($result) === true)
            {
                return strtolower(implode('+', $result));
            }
        }

        return false;
    }
}

?>

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

Есть ли другие способы решения этой проблемы?

EDIT - Некоторые примеры использования:

<code><?php

$images = new TagFS('S:');

$images->Add('P:/xampplite/htdocs/tag/geoaki.png', 'geoaki logo');
$images->Add('P:/xampplite/htdocs/tag/cloud.jpg', 'geoaki cloud tag');
$images->Add('P:/xampplite/htdocs/tag/cloud.jpg', 'nuvem azul branco');
$images->Add('P:/xampplite/htdocs/tag/xml-full.gif', 'geoaki auto vin api service xml');
$images->Add('P:/xampplite/htdocs/tag/dunp3d-1.jpg', 'dunp logo');
$images->Add('P:/xampplite/htdocs/tag/d-proposta-04c.jpg', 'dunp logo');

/*
[0] => S:/+api+auto+geoaki+service+vin+xml+29be189cbc98fcb36a44d77acad13e18.gif
[1] => S:/+azul+branco+nuvem+4151ae7900f33788d0bba5fc6c29bee3.jpg
[2] => S:/+cloud+geoaki+tag+4151ae7900f33788d0bba5fc6c29bee3.jpg
[3] => S:/+dunp+logo+0cedeb6f66cbfc3974c6b7ad86f4fbd3.jpg
[4] => S:/+dunp+logo+8b9fcb119246bb6dcac1906ef964d565.jpg
[5] => S:/+geoaki+logo+5f5174c498ffbfd9ae49975ddfa2f6eb.png
*/
echo '<pre>';
print_r($images->Get('*'));
echo '
'; / * [0] => S: / + azul + branco + nuvem + 4151ae7900f33788d0bba5fc6c29bee3.jpg * / echo '
';
print_r($images->Get('azul nuvem'));
echo '
'; / * [0] => S: / + dunp + logo + 0cedeb6f66cbfc3974c6b7ad86f4fbd3.jpg [1] => S: / + dunp + logo + 8b9fcb119246bb6dcac1906ef964d565.jpg [2] => S: / + geoaki + logo + 5f5174c498ffbfd9ae49975ddfa2f6eb.png * / echo '
';
print_r($images->Get('logo'));
echo '
'; / * [0] => S: / + dunp + logo + 0cedeb6f66cbfc3974c6b7ad86f4fbd3.jpg [1] => S: / + dunp + logo + 8b9fcb119246bb6dcac1906ef964d565.jpg * / echo '
';
print_r($images->Get('logo dunp'));
echo '
'; / * [0] => S: / + geoaki + logo + 5f5174c498ffbfd9ae49975ddfa2f6eb.png * / echo '
';
print_r($images->Get('geo* logo'));
echo '
'; ?>

РЕДАКТИРОВАТЬ: В связи с несколькими предложениями использовать базу данных без сервера или любой другой тип таблицы поиска (XML, плоские, пары ключ / значение и т. Д.), Я хочу уточнить следующее: хотя этот код написан на PHP, идея состоит в том, чтобы перенести его на Python и сделать из него приложение для настольного компьютера - это не имеет никакого отношения (помимо примера, конечно) к PHP. Кроме того, , если мне нужно использовать какую-то таблицу поиска, я определенно пойду с SQLite 3, но то, что я ищу, - это решение, которое не требует каких-либо других дополнительных "технологий", кроме файловая система (папки, файлы и жесткие ссылки).

Вы можете назвать меня чокнутым, но я пытаюсь достичь двух простых целей: 1) освободить систему от "мусора" (например, кому нравится Thumbs.db или DS_STORE?) И 2) сохранить файлы легко идентифицируется, если по какой-то причине справочная таблица (в данном случае SQLite) становится занятой, поврежденной, потерянной или забытой (например, в резервных копиях).

PS: предполагается, что он будет работать как в Linux, Mac, так и в Windows (под NTFS).

Ответы [ 14 ]

16 голосов
/ 19 мая 2009

Если у вас есть жесткие / мягкие ссылки, вы можете подумать о том, чтобы присвоить каждому тегу собственный каталог, содержащий ссылку для каждого файла с этим «тегом». Затем, когда вам дают несколько тегов, вы можете сравнить найденные в обоих. Тогда файлы могут быть сохранены в одной папке и иметь уникальное имя, конечно.

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

4 голосов
/ 22 мая 2009

Я бы вставил эту информацию в базу данных, даже если она облегченная, как файл sqlite в том же каталоге.

Если вы не хотите этого делать, вы можете создать жесткие ссылки на файл без каких-либо перестановок. Один файл на тег. Пометка P: /xampplite/htdocs/tag/geoaki.png с geoaki и логотипом приведет к тому, что два файла будут жесткими ссылками, указывающими на те же данные, что и исходный файл:

  • P: /xampplite/htdocs/tag/geoaki.png.geoaki)
  • P: /xampplite/htdocs/tag/geoaki.png.logo)

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

# All tags
$tags = array();
files = glob('P:/xampplite/htdocs/tag/geoaki.png.*')
foreach ($files as $file) {
    if (fileinode($file) === fileinode('P:/xampplite/htdocs/tag/geoaki.png')) {
        $tags[] = substr($file, strlen('P:/xampplite/htdocs/tag/geoaki.png.'));
    }
}

# Check if file has tag foo:
file_exists('P:/xampplite/htdocs/tag/geoaki.png.foo')
    && fileinode(P:/xampplite/htdocs/tag/geoaki.png.foo) === fileinode('P:/xampplite/htdocs/tag/geoaki.png');

Еще одна вещь: полагаться только на хеши md5 для идентификации файлов небезопасно, лучше использовать имя файла в качестве идентификатора, который гарантированно будет уникальным в папке. Отрицательные эффекты md5 как идентификатора:

  • Система ломается, как только файл изменяется
  • В md5 есть коллизии, два разных файла могут иметь одинаковый хэш md5 (вероятность мала, но существует)
4 голосов
/ 18 мая 2009

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

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

3 голосов
/ 23 мая 2009

Вы достаточно сузили вопрос, и я считаю, что ответ: «Нет».

Вам не нужен центральный реестр тегов, потому что он может быть поврежден.

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

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

Вы наверняка не хотите помещать теги в содержимое самих файлов.

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

Нет. (Или, по крайней мере, нет ничего портативного).

Конечно, негде хранить метаданные, кроме как в имени файла или в самом файле, который останется с файлом (когда он копируется и перемещается с использованием обычных инструментов), который будет работать во всех трех основных операционных системах. Вы упоминаете (Linux, Mac, Win).

Было бы неплохо, если бы существовала портативная система метаданных, которая могла бы сделать это, но это не так. У меня сложилось впечатление, что нет единого мнения о том, как лучше всего делать пометки. Таким образом, каждая система делает это по-своему и со своим набором компромиссов.

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

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

Может быть, кто-то написал библиотеку для Python, которая уже делает это?

C.J.

2 голосов
/ 25 мая 2009

Больше мозгового штурма, чем ответа.

Как указал @CJ, без каких-либо внешних метаданных и с ограничением в 255 байт в качестве идентификатора имени файла плюс «облако тегов» ваши теги остаются проблемой.

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

  1. вычислить контрольную сумму или хэш для данного файла
  2. сохранить символическую ссылку в каком-либо формате, например -тег или тег-

Я понимаю, это то, что вы подразумеваете под "мусором", но если вы хотите хранить произвольное количество произвольных тегов в строке фиксированной длины, вы столкнетесь с информационным барьером рано или поздно. использование базы данных лучше масштабируется, но хранение и извлечение символических ссылок должно быть легко осуществимым. «мусор» может храниться в одном хранилище метаданных с ведущая точка, которая является широко используемой и установившейся практикой в ​​некоторых операционных системах.

удачи!

1 голос
/ 28 мая 2009

Если ваша операционная система и файловая система поддерживают расширенные атрибуты файлов, используйте их для хранения тегов. В OS X и FreeBSD см. Справочные страницы setxattr и getxattr; Linux и Solaris имеют схожие возможности. В Windows есть поддержка расширенных атрибутов в NTFS. Смотрите "расширенные атрибуты файла" в Википедии для получения дополнительной информации.

1 голос
/ 28 мая 2009

Файловая система - это ваша база данных, поэтому используйте ее.

  1. Придумайте «уникальное имя» для вашего файла. Неважно, как называется файл, если он уникален по всему пространству. Имя файла не имеет ничего общего с тегами.

  2. Хэшируйте имя файла в каталог «хранилище». Если вы не собираетесь иметь bazillion файлов (<1000-2000), вы можете хранить все файлы в одном каталоге. В противном случае создайте несколько каталогов «bucket» и добавьте файл в правильный каталог. Этот процесс, очевидно, является детерминированным на основе имени файла. </p>

  3. Для каждого тега в файле либо храните «пустой» файл с тем же именем в каталоге «тегов», либо просто создайте «файл тегов», в котором перечислены файлы в этом теге. Опять же, если вы ожидаете, что в конкретном теге содержится миллионы файлов, добавьте файлы в сегменты.

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

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

Если вы хотите сохранить фактические метаданные для файла, то создайте зеркальный каталог «метаданных». Когда вы добавляете файл, вы помещаете его в каталог хранилища файлов, а соответствующий файл метаданных - в каталог «хранилища метаданных», используя ту же схему. Удаление файла путем удаления оригинала и его метаданных.

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

Это дает вам «неограниченное» количество тегов на файл, вы можете управлять им из командной строки или из файлового брайзера, используя только необходимый инструмент - глазное яблоко Mark I. Вы также получаете постоянные ссылки на фактический файл (так как его имя никогда не меняется).

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

1 голос
/ 26 мая 2009

На самом деле, я создал реализацию этой утилиты для сценариев оболочки и интегрировал ее с файловым браузером nautilus ...

Я использовал подход мягких ссылок: каталог с именем .tags содержал все «теги», а теги были просто каталогами в каталоге .tags.

Если файл был помечен как "fun", то в .tags / fun будет создана мягкая ссылка на него. Однако этот метод не подходит для поиска по тегам.

Если вы хотите поддержать поиск, я рекомендую использовать sqlite.

ура, мл.

0 голосов
/ 08 июля 2013

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

вопрос в том, могут ли другие системы считывать эти комментарии и данные из свойств файла Windows?

0 голосов
/ 23 мая 2009

«Какой подход я должен использовать, чтобы обойти ограничение имени файла?»

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...