Php “标签上的问题”;“文件系统”;
出于娱乐的原因,我编写了一个PHP类,它使用标记而不是分层方式对文件进行分类,标记以+tag1+tag2+tagN+MD5.EXTENSION的形式存储在文件名中,因此我被FS/OS强加的字符限制(255)所困扰。下面是课堂:Php “标签上的问题”;“文件系统”;,php,language-agnostic,file,operating-system,filesystems,Php,Language Agnostic,File,Operating System,Filesystems,出于娱乐的原因,我编写了一个PHP类,它使用标记而不是分层方式对文件进行分类,标记以+tag1+tag2+tagN+MD5.EXTENSION的形式存储在文件名中,因此我被FS/OS强加的字符限制(255)所困扰。下面是课堂: <?php class TagFS { public $FS = null; function __construct($FS) { if (is_dir($FS) === true) {
<?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;
}
}
?>
Add('P:/xampplite/htdocs/tag/dunp3d-1.jpg','dunplogo');
$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+徽标+5f5174c498ffbfd9ae49975ddfa2f6eb.png
*/
回声';
打印($images->Get('*');
回声';
/*
[0]=>S:/+azul+branco+nuvem+4151ae7900f33788d0bba5fc6c29bee3.jpg
*/
回声';
打印($images->Get('azul nuvem'));
回声';
/*
[0]=>S:/+dunp+logo+0cedeb6f66cbfc3974c6b7ad86f4fbd3.jpg
[1] =>S:/+dunp+logo+8b9fcb119246bb6dcac1906ef964d565.jpg
[2] =>S:/+geoaki+徽标+5f5174c498ffbfd9ae49975ddfa2f6eb.png
*/
回声';
打印($images->Get('logo'));
回声';
/*
[0]=>S:/+dunp+logo+0cedeb6f66cbfc3974c6b7ad86f4fbd3.jpg
[1] =>S:/+dunp+logo+8b9fcb119246bb6dcac1906ef964d565.jpg
*/
回声';
打印($images->Get('logo dunp'));
回声';
/*
[0]=>S:/+geoaki+徽标+5f5174c498ffbfd9ae49975ddfa2f6eb.png
*/
回声';
打印($images->Get('geo*logo'));
回声';
?>
EDIT:由于有几条建议使用无服务器数据库或任何其他类型的查找表(XML、平面、键/值对等),我想澄清以下几点:虽然这段代码是用PHP编写的,但想法是将其移植到Python并用其制作桌面应用程序-这没有什么要做的(当然除了示例之外)使用PHP。此外,如果我必须使用某种查找表,我肯定会使用SQLite 3,但我要寻找的是一种解决方案,它不涉及除文件系统(文件夹、文件和硬链接)之外的任何其他“技术”。
你可能会说我疯了,但我在这里试图实现两个简单的目标:1)保持系统“无垃圾”(例如谁喜欢Thumbs.db或DS_STORE?)和2)如果出于某种原因查找表(在本例中是SQLite)变得繁忙、损坏、丢失或忘记(例如在备份中),则保持文件易于识别。
PS:这应该在Linux、Mac和Windows(NTFS下)上运行。您应该将标记设置为目录,而不是文件名元素,即,而不是
/dir/tag1+tag2+tagN+MD5.EXT
,/dir/tag1/tag2/tagN/MD5.EXT
。您将目录层次结构视为需要避免的事情,这在多个方面都是自食其果
如果因为您认为很难按需生成目录结构而采取这种避免措施,那么您应该研究第三个参数,
$recursive
,to.您可能希望为您关心的每个文件夹创建标记缓存,类似于Windows在浏览文件夹时创建文件以缓存拇指的方式
创建这样的元数据文件的优点是可以跨多个不同的文件系统工作,而不会遇到文件名限制。如果您使用硬/软链接,那么您可以考虑为每个标记指定自己的目录,每个文件都有一个带有该“标记”的链接然后,当您得到多个标记时,您可以比较这两个标记中的标记。然后,这些文件可以存储在一个文件夹中,当然,它们的名称是唯一的
我不知道这与使用标记命名的元文件,然后列出该标记中存在的所有文件有什么不同。如果您不想使用数据库,为什么不尝试使用xml,您可以这样列出所有数据:
MD5
tag5+tag4+tag3
您可以轻松地添加更多类似标题和描述的信息。我会将这些信息插入数据库,即使它是一个轻量级的数据库,比如同一目录中的sqlite文件 如果您不想这样做,您可以创建指向该文件的硬链接,而无需任何排列。每个标签一个文件。使用geoaki和logo标记P:/xamplite/htdocs/tag/geoaki.png将导致两个文件都是硬链接,指向与原始文件相同的数据:
- P:/xamplite/htdocs/tag/geoaki.png.geoaki)
- P:/xamplite/htdocs/tag/geoaki.png.logo)
- 一旦文件发生更改,系统就会中断
- md5中存在冲突,两个不同的文件可能具有相同的md5哈希(概率很小,但存在)
ls.*aa.*f3.*yz.
”,这将挑选出包含所有这些代码的文件名。选择
<?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>';
?>
<file>
<md5>MD5</md5>
<body>tag5+tag4+tag3</body>
</file>
# 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');