В рекреационных целях я написал класс 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 – некоторые примеры использования:
<?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 '</pre>'; /* [0] => S:/+azul+branco+nuvem+4151ae7900f33788d0bba5fc6c29bee3.jpg */ echo '<pre>'; print_r($images->Get('azul nuvem')); echo '</pre>'; /* [0] => S:/+dunp+logo+0cedeb6f66cbfc3974c6b7ad86f4fbd3.jpg [1] => S:/+dunp+logo+8b9fcb119246bb6dcac1906ef964d565.jpg [2] => S:/+geoaki+logo+5f5174c498ffbfd9ae49975ddfa2f6eb.png */ echo '<pre>'; print_r($images->Get('logo')); echo '</pre>'; /* [0] => S:/+dunp+logo+0cedeb6f66cbfc3974c6b7ad86f4fbd3.jpg [1] => S:/+dunp+logo+8b9fcb119246bb6dcac1906ef964d565.jpg */ echo '<pre>'; print_r($images->Get('logo dunp')); echo '</pre>'; /* [0] => S:/+geoaki+logo+5f5174c498ffbfd9ae49975ddfa2f6eb.png */ echo '<pre>'; print_r($images->Get('geo* logo')); echo '</pre>'; ?>
EDIT: Из-за нескольких предложений по использованию безсерверной базы данных или любого другого типа таблицы поиска (XML, flat, пары ключ / значение и т. Д.) Я хочу пояснить следующее: хотя этот код написан на PHP, идея состоит в том, чтобы переносите его на Python и вынимайте из него настольное приложение – это, как предполагается, (помимо примера, конечно) с PHP. Кроме того, если мне нужно использовать какую-то таблицу поиска, я обязательно займусь SQLite 3, но то, что я ищу, – это решение, которое не включает в себя какую-либо дополнительную «технологию» помимо файловой системы (папки, файлы и жесткие ссылки).
Вы можете называть меня орехами, но я пытаюсь выполнить две простые цели здесь: 1) сохранить систему «мусор» бесплатно (кому нравится Thumbs.db или DS_STORE, например?) И 2) держать файлы легко идентифицируемыми, если по какой-либо причине таблица поиска (в данном случае SQLite) становится занятой, коррумпированной, потерянной или забытой (например, в резервных копиях).
PS: Предполагается, что он будет работать как на Linux, Mac, так и на Windows (под NTFS).
Если у вас есть жесткие / мягкие ссылки, чем вы можете посмотреть на то, чтобы каждый тег был собственным каталогом, имеющим ссылку для каждого файла с этим «тегом». Затем, когда вам дается несколько тегов, вы можете сравнить их в обоих. Затем файлы могут храниться в одной папке и иметь их уникальные имена.
Я не знаю, как это будет отличаться от метафайла, указанного тегом, а затем перечисления всех файлов, существующих в этом теге.
Возможно, вы захотите создать кеш тегов для каждой связанной вами папки, подобно тому, как Windows создает файл Thumbs.db для кэширования больших пальцев при просмотре папок.
Создание файла метаданных, подобного этому, имеет преимущество в работе во многих разных файловых системах, не сталкиваясь с ограничением имени файла.
Я бы вставлял эту информацию в базу данных, даже если она легкая, как файл sqlite в том же каталоге.
Если вы не хотите этого делать, вы можете создавать жесткие ссылки на файл без каких-либо перестановок. Один файл для каждого тега. Пометка P: /xampplite/htdocs/tag/geoaki.png с geoaki и логотипом приведет к тому, что два файла будут жесткими, указывающими на те же данные, что и исходный файл:
Это имеет то преимущество, что вы можете выбрать все теги, принадлежащие этому файлу, с помощью 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 в качестве идентификатора являются:
Вы достаточно сузили вопрос, я верю, что ответ: «Нет».
Вам не нужен центральный реестр тегов, потому что он может стать поврежденным.
Вы не хотите, чтобы файлы или файлы были скрыты в каждом каталоге для хранения данных, поскольку это «мусор».
Вероятно, вам не нужен параллельный набор каталогов или каталогов со ссылками, потому что тогда он устаревает, когда вы перемещаете вещи и, вероятно, составляете «мусор» в файловой системе.
Вы, конечно же, не хотите помещать теги в содержимое самих файлов.
Так где-нибудь еще вы могли бы помещать теги в сторону от имени файла в структуре каталогов?
Нет. (Или, по крайней мере, нет ничего портативного).
Конечно, хранить метаданные не следует, кроме как в имени файла, так и в самом фактическом файле, который останется с файлом (когда он будет скопирован и перенесен с использованием обычных инструментов), который будет работать во всех трех основных операционных системах, о которых вы упоминаете ( Linux, Mac, Win).
Было бы неплохо, если бы была портативная система метаданных, которая могла бы это сделать, но нет. У меня сложилось впечатление, что нет общего согласия в отношении того, какой лучший способ сделать тегирование. Поэтому каждая система делает это по-разному и с другим набором компромиссов.
Я думаю, что по сравнению с большинством основных идей в операционных системах (иерархические файловые системы, интерфейсы графического интерфейса и т. Д.) Использование тегов – относительно новая идея. Большинство объектов, разделяемых во всех трех системах, являются довольно старыми и устоявшимися идеями.
Лучше всего, наверное, изучить, как каждая система это делает, а затем написать библиотеку, которая обеспечила бы портативный доступ к самым низким общим знаменателям функциональности между системами.
Может быть, кто-то написал библиотеку для Python, которая делает это уже?
CJ
Больше мозговой штурм, чем ответ.
Как отметил @CJ, без каких-либо внешних метаданных и с ограничением 255 байтов в качестве идентификатора имени файла плюс «tag-cloud» ваши теги будут оставаться проблемой.
Символические ссылки хороши. Вместо того, чтобы упаковывать все тэги в одно имя файла, можно было бы распространять теги по нескольким файлам, или – ради пространства – символические ссылки. шаги:
Я понимаю, это то, что вы подразумеваете под «мусором», но если вы хотите сохранить произвольное количество произвольных тегов в строке с фиксированной длиной, вы рано или поздно попадете в информационный барьер. использование базы данных лучше, но сохранять и извлекать символические ссылки следует легко реализовать. «мусор» может храниться в одном репозитории метаданных с ведущей «точкой», которая является широко используемой и установленной в некоторых операционных системах.
удачи!
на самом деле, я построил реализацию сценария оболочки для этой утилиты и интегрировал его с браузером файлов nautilus …
Я использовал метод софт-ссылок: в каталоге под названием .tags содержались все «теги», а теги были просто каталогами в каталоге .tags.
Если файл был помечен как «fun», тогда мягкая ссылка на него будет создана в .tags / fun .. Однако этот метод не подходит для поиска по тегам.
Если вы хотите также поддерживать поиск, я рекомендую использовать sqlite.
приветствия, jrh.
Файловая система – это ваша база данных, поэтому используйте ее.
Придумайте «уникальное имя» для вашего файла. Неважно, что такое имя файла, если оно уникально по всему пространству. Имя файла не имеет ничего общего с тегами.
Хешируйте имя файла в папку «storage». Если у вас нет файлов bazillion (<1000-2000), вы можете сохранить все файлы в одном каталоге. В противном случае создайте кучу каталогов «bucket» и перетащите файл в правильный каталог. Этот процесс, очевидно, детерминирован на основе имени файла.
Для каждого тега в файле либо сохраните «пустой» файл с тем же именем в каталоге «tag», либо просто получите «файл тега», в котором перечислены файлы в этом теге. Опять же, если вы ожидаете получить файлы в отдельном теге, сделайте хэширование файлов в ведрах.
Чтобы добавить тег в файл, просто добавьте ссылку на файл в соответствующий тег. Чтобы удалить тег, то же самое.
Чтобы удалить файл, просто удалите файл из основного хранилища. Когда вы повторяете ссылки на теги, вы можете проверить файл в этой точке и удалить записи лениво. В любом случае вы, вероятно, будете бить файл за что-нибудь интересное.
Если вы хотите сохранить фактические метаданные для файла, создайте зеркальный каталог «метаданные». Когда вы добавляете файл, вы поместите его в каталог хранилища файлов и соответствующий файл метаданных в каталог «хранилище метаданных», используя ту же схему. Удаление файла путем удаления оригинала и его метаданных.
Просто простые файловые операции, отсутствие файловой системы shenanigans (за пределами хеширования ведра каталога), никаких ссылок, атрибутов, что у вас есть.
Это дает вам «неограниченные» теги для каждого файла, вы можете управлять им из командной строки или проводника файлов с помощью единственного инструмента, который должен быть Mark I Eyeball. Вы также получаете постоянные ссылки на фактический файл (так как имя никогда не изменяется).
Самая темная часть заключается в том, что вам нужно «сканировать облако тегов», чтобы узнать, какие теги имеют файл. Если вы решите пойти с файлом метаданных, вы можете сохранить в нем список тегов (что усложнит ваши операции пометки / разметки, но не ужасно).
Если ваша операционная система и файловая система поддерживают расширенные атрибуты файлов, используйте это для хранения тегов. В OS X и FreeBSD см. Страницы руководства setxattr и getxattr; У Linux и Solaris есть аналогичные возможности. Windows поддерживает расширенные атрибуты в NTFS. Дополнительную информацию см. В разделе «Расширенные атрибуты файлов» в wikipedia.
Вы должны сделать каталоги тегов вместо элементов имени файла, т. /dir/tag1+tag2+tagN+MD5.EXT
Вместо /dir/tag1+tag2+tagN+MD5.EXT
, /dir/tag1/tag2/tagN/MD5.EXT
. Вы стреляете в ногу несколькими способами, рассматривая иерархию каталогов как нечто, чего следует избегать.
Если вы участвуете в этом избегании, потому что считаете, что создавать структуру каталогов по требованию сложно, вы должны изучить третий аргумент, $recursive
, для PHP mkdir .
Выбор, чтобы избежать SQLite, потому что это «не родной PHP», кажется ложной дихотомией, поскольку он скомпилирован почти в каждое практическое распространение PHP. Если вы предпочитаете не-SQL-решение, berkeleydb предоставляет простое хранилище ключей, которое вы можете использовать для связывания списка имен файлов с любыми именами файлов тегов со списками тегов.
Но идите с решением SQL. Он будет быстрым, портативным и простым, чем вы думаете.
«Какой подход следует принять, чтобы обойти ограничение на имя файла?»
Как насчет файловой системы, поддерживающей теги? Tagsistant Вы не указали свою операционную систему.
В окнах вы можете щелкнуть правой кнопкой мыши по файлу> свойства и добавить комментарий и другие данные. Вы можете использовать это для своей системы тегов (конечно, пользователь может очень легко возиться с ним, КОТОРЫЙ ОК)
вопрос в том, могут ли другие системы читать эти комментарии и данные из свойств файла Windows?
Если вы не хотите использовать базу данных, почему бы не попробовать xml, вы можете перечислить все свои данные следующим образом:
<file> <md5>MD5</md5> <body>tag5+tag4+tag3</body> </file>
Вы можете легко добавить больше, как название и описание.
вся точка тегов – это возможность быстро искать несколько комбинаций тегов. в идеале вы хотите иметь базу данных с таблицей тегов {tag, path-to-file}. если вы настроились на сохранение ваших тегов в имени файла, вам нужно использовать какое-то сжатие. сохраняйте таблицу поиска (db или flat file), сопоставляя каждый тег с 2-символьным кодом (например, aa: tag1, ab: tag2, ac: tag3 …). придерживаясь ascii, это должно дать вам теги ~ 10k, если этого недостаточно, используйте три символа. теперь ваше имя будет чем-то вроде aa.ag.f2.gx.ty.extension
Еще один момент, который следует отметить, заключается в том, что, поскольку вы хотите выполнять поиск по нескольким тегам, вы хотите убедиться, что коды тегов в вашем имени файла находятся в строгом лексическом порядке. затем, для поиска по тегам aa, f3 и yz сразу, сделайте « ls .*aa.*f3.*yz.*
», который выберет имена файлов, содержащие все эти коды.