使用Coldfusion(递归)搜索文件夹中的重复照片?
在移动和备份我的照片集几次之后,我有几张重复的照片,不同的文件名分散在我的PC上的不同文件夹中。因此我想我应该写一个快速的CF(9)页面来查找重复的照片(然后可以稍后添加代码以允许我删除它们) 我有几个问题:-使用Coldfusion(递归)搜索文件夹中的重复照片?,coldfusion,duplicates,Coldfusion,Duplicates,在移动和备份我的照片集几次之后,我有几张重复的照片,不同的文件名分散在我的PC上的不同文件夹中。因此我想我应该写一个快速的CF(9)页面来查找重复的照片(然后可以稍后添加代码以允许我删除它们) 我有几个问题:- 目前,我只是使用文件大小来匹配图像文件,但我认为匹配EXIF数据或匹配图像文件二进制的哈希值更可靠 我拼凑的代码有点有用,但如何在web根目录之外进行搜索呢 有更好的办法吗 p #名称[i]##目录[i]# 没有找到重复的JPG 我建议将检查代码拆分为只接受文件名的函数 然后使用全局结
#名称[i]#
#目录[i]#
没有找到重复的JPG
我建议将检查代码拆分为只接受文件名的函数
然后使用全局结构检查重复项,键为“size”或“size\u hash”,值可以是一个数组,该数组将包含与该键匹配的所有文件名
对所有不同目录中的所有jpeg文件运行该函数,然后扫描结构并报告其数组中包含多个文件的所有条目
如果您想在webroot之外显示图像,可以通过
<cfsetting enablecfoutputonly="true" />
<cfset ticks = getTickCount() />
<!--- this is great set of utils from Apache --->
<cfset digestUtils = CreateObject("java","org.apache.commons.codec.digest.DigestUtils") />
<!--- cache containers --->
<cfset checksums = {} />
<cfset duplicates = {} />
<cfdirectory
action="list"
name="images"
directory="/home/trovich/images/"
filter="*.png|*.jpg|*.jpeg|*.gif"
recurse="true" />
<cfloop query="images">
<!--- change delimiter to \ if you're on windoze --->
<cfset ipath = images.directory & "/" & images.name />
<cffile action="readbinary" file="#ipath#" variable="binimage" />
<!---
This is slow as hell with any encoding!
<cfset checksum = BinaryEncode(binimage, "Base64") />
--->
<cfset checksum = digestUtils.md5hex(binimage) />
<cfif StructKeyExists(checksums, checksum)>
<!--- init cache using original on 1st position when duplicate found --->
<cfif NOT StructKeyExists(duplicates, checksum)>
<cfset duplicates[checksum] = [] />
<cfset ArrayAppend(duplicates[checksum], checksums[checksum]) />
</cfif>
<!--- append current duplicate --->
<cfset ArrayAppend(duplicates[checksum], ipath) />
<cfelse>
<!--- save originals only into the cache --->
<cfset checksums[checksum] = ipath />
</cfif>
</cfloop>
<cfset time = NumberFormat((getTickcount()-ticks)/1000, "._") />
<!--- render duplicates without resizing (see options of cfimage for this) --->
<cfoutput>
<h1>Found #StructCount(duplicates)# duplicates, took ~#time# s</h1>
<cfloop collection="#duplicates#" item="checksum">
<p>
<!--- display all found paths of duplicate --->
<cfloop array="#duplicates[checksum]#" index="path">
#HTMLEditFormat(path)#<br/>
</cfloop>
<!--- render only last duplicate, they are the same image any way --->
<cfimage action="writeToBrowser" source="#path#" />
</p>
</cfloop>
</cfoutput>
找到#StructCount(重复项)#重复项,花费了#时间#
#HTMLEditFormat(路径)#
显然,您可以轻松地使用duplicates
array来查看结果和/或运行一些清理作业
玩得开心 +1同样,这将确定哈希比较部分,谢谢Sergii。如何对其进行修改以处理同一图像/文件的2个以上副本?目前,如果您有3个相同的副本,那么您的代码将标识2个副本。另外,如何在web根目录之外显示图像预览?@Saul请检查更新的代码示例,我对其进行了一些修改。相同图像的所有实例现在都分组了,我同意这对于分析更方便。图像输出非常简单,但代价是图像以原始大小显示——对于大图像和/或少量图像,这将是非常慢的。。文件IO和操作系统级别的散列将更快更容易?@Henry:同意,但做操作系统级别散列的正确方法是什么?提供一个例子。@Henry这取决于您想要什么:根据您的个人需要解决任务,并享受CFML带来的乐趣(顺便说一句,我认为使用ApacheLib进行哈希运算非常快,但渲染不是),或者尽可能高效地解决任务。为了第二个目的,我会使用一个很好的现有工具,比如(Ubuntu)。
<cfsetting enablecfoutputonly="true" />
<cfset ticks = getTickCount() />
<!--- this is great set of utils from Apache --->
<cfset digestUtils = CreateObject("java","org.apache.commons.codec.digest.DigestUtils") />
<!--- cache containers --->
<cfset checksums = {} />
<cfset duplicates = {} />
<cfdirectory
action="list"
name="images"
directory="/home/trovich/images/"
filter="*.png|*.jpg|*.jpeg|*.gif"
recurse="true" />
<cfloop query="images">
<!--- change delimiter to \ if you're on windoze --->
<cfset ipath = images.directory & "/" & images.name />
<cffile action="readbinary" file="#ipath#" variable="binimage" />
<!---
This is slow as hell with any encoding!
<cfset checksum = BinaryEncode(binimage, "Base64") />
--->
<cfset checksum = digestUtils.md5hex(binimage) />
<cfif StructKeyExists(checksums, checksum)>
<!--- init cache using original on 1st position when duplicate found --->
<cfif NOT StructKeyExists(duplicates, checksum)>
<cfset duplicates[checksum] = [] />
<cfset ArrayAppend(duplicates[checksum], checksums[checksum]) />
</cfif>
<!--- append current duplicate --->
<cfset ArrayAppend(duplicates[checksum], ipath) />
<cfelse>
<!--- save originals only into the cache --->
<cfset checksums[checksum] = ipath />
</cfif>
</cfloop>
<cfset time = NumberFormat((getTickcount()-ticks)/1000, "._") />
<!--- render duplicates without resizing (see options of cfimage for this) --->
<cfoutput>
<h1>Found #StructCount(duplicates)# duplicates, took ~#time# s</h1>
<cfloop collection="#duplicates#" item="checksum">
<p>
<!--- display all found paths of duplicate --->
<cfloop array="#duplicates[checksum]#" index="path">
#HTMLEditFormat(path)#<br/>
</cfloop>
<!--- render only last duplicate, they are the same image any way --->
<cfimage action="writeToBrowser" source="#path#" />
</p>
</cfloop>
</cfoutput>