脚本应用之一:查找并删除重复文件

作用:查找指定目录(一个或多个)及子目录下的所有重复文件,分组列出,并可手动选择或自动随机删除多余重复文件,每组重复文件仅保留一份。(支持文件名有空格,例如:"file  name" 等)

实现:find遍历指定目录查找所有文件,并对找到的所有文件进行MD5校验,通过比对MD5值分类处理重复文件。

不足:  find 遍历文件耗时;

MD5校验大文件耗时;

对所有文件校验比对耗时(可考虑通过比对文件大小进行第一轮的重复性筛选,此方式针对存放大量大文件的目录效果明显,本脚本未采用);

演示:

注释:

脚本执行过程中显示MD5校验过程,完毕后,统计信息如下:

Files: 校验的文件总数

Groups: 重复文件组的数量

Size:此处统计的大小为,多余文件的总大小,即将要删除的多余的重复文件的大小,换句话说就是,删除重复文件后,磁盘空间会节省的空间。

可在“Show detailed information ?”提示后,按键“y”,进行重复文件组的查看,以便确认,也可直接跳过,进入删除文件方式的选择菜单:

删除文件方式有两种,一种是手动选择方式(默认的方式),每次列出一组重复文件,手动选择欲留下的文件,其他文件将会被删除,若没有选择 则默认保留列表的第一个文件,演示如下:

另一种方式是自动选择方式,默认保留每组文件的第一个文件,其他重复文件自动删除。(为防止删除重要文件,建议使用第一种方式),演示如下:

支持文件名空格的情况,演示如下:

代码专区:

#!/bin/bash
#Author: LingYi
#Date: 2016.4.12
#Func: Delete duplicate files
#EG  : $0 [ DIR1 DIR2 ... DIRn ]

#定义临时文件,自行确定用户的写入权限
md5sum_result_log="/tmp/$(date +%Y%m%d%H%M%S)"

echo -e "\033[1;31mMd5suming ...\033[0m"

#遍历目录,校验文件并做输出和写入临时文件
find [email protected] -type f -print0 | xargs -0 -I {} md5sum {} | tee -a $md5sum_result_log
files_sum=$(cat $md5sum_result_log | wc -l)

#定义数组,此数组的索引为文件的MD5值,元素为文件名称,因此需要提前声明(需要bash支持)
declare -A md5sum_value_arry

while read md5sum_value md5sum_filename
do 
    #为了支持文件名有空格的情况,使用“+”代替空格符作为分隔个个文件名的分隔符
    #因此,文件名若带有“+",则脚本执行结果会有问题,需要用户删除文件时,选择手动选择模式以便确认
	md5sum_value_arry[$md5sum_value]="${md5sum_value_arry[$md5sum_value]}+$md5sum_filename"
	(( _${md5sum_value}+=1 ))
done <$md5sum_result_log

#此循环实现统计重复文件的组数据并对多余文件的大小做统计
groups_sum=0
repfiles_size=0
for md5sum_value_index in ${!md5sum_value_arry[@]}
do
	if eval [[ \${_${md5sum_value_index}} -gt 1 ]]; then
		let groups_sum++
		need_print_indexes="$need_print_indexes $md5sum_value_index"
		eval repfile_sum=\$\(\( \$_$md5sum_value_index - 1 \)\)
		repfile_size=$( ls -lS "`echo ${md5sum_value_arry[$md5sum_value_index]}|awk -F‘+‘ ‘{print $2}‘`" | awk ‘{print $5}‘)
		repfiles_size=$(( repfiles_size + repfile_sum*repfile_size ))
	fi
done 

#输出统计信息
echo -e "\033[1;31mFiles: $files_sum    Groups: $groups_sum    Size: ${repfiles_size}B $((repfiles_size/1024))K $((repfiles_size/1024/1024))M\033[0m"
[[ $groups_sum -eq 0 ]] && exit

#用户选择是否查看重复文件的分组详情。
read -n 1 -s -t 300 -p ‘Show detailed information ?‘ user_ch
[[ $user_ch == ‘n‘ ]] && echo || {
	[[ $user_ch == ‘q‘ ]] && exit
	for print_value_index in $need_print_indexes
	do
		echo -ne "\n\033[1;35m$((++i)) \033[0m"
		eval echo -ne "\\\033[1\;34m$print_value_index [ \$_${print_value_index} ]:\\\033[0m"
		echo ${md5sum_value_arry[$print_value_index]} | tr ‘+‘ ‘\n‘
	done | more
}

#用户选择删除文件的方式
echo -e "\n\nManual Selection by default !"
echo -e " 1 Manual selection\n 2 Random selection" 
echo -ne "\033[1;31m"
read -t 300 USER_CH
echo -ne "\033[0m"
[[ $USER_CH == ‘q‘ ]] && exit
[[ $USER_CH -ne 2 ]] && USER_CH=1 || {
	echo -ne "\033[31mWARNING: you have choiced the Random Selection mode, files will be deleted at random !\nAre you sure ?\033[0m"
	read -t 300  yn
	[[ $yn == ‘q‘ ]] && exit
	[[ $yn != ‘y‘ ]] && USER_CH=1
}

#根据用户选择的方式,进行处理
echo -e "\033[31m\nWarn: keep the first file by default.\033[0m"
for exec_value_index in $need_print_indexes
do
    #此循环获取包含即将删除的文件的数组
	for((i=0,j=2;i<$(echo ${md5sum_value_arry[$exec_value_index]} | grep -o ‘+‘ | wc -l); i++,j++))
	do 
		file_choices_arry[i]="$(echo ${md5sum_value_arry[$exec_value_index]}|awk -F‘+‘ ‘{print $J}‘ J=$j)"
	done

	eval file_sum=\$_$exec_value_index
	if [[ $USER_CH -eq 1 ]]; then
	        #如果用户选择手动模式,则循环输出重复文件分组,并一一处理
		echo -e "\033[1;34m$exec_value_index\033[0m"
		for((j=0; j<${#file_choices_arry[@]}; j++))
		do
			echo "[ $j ]  ${file_choices_arry[j]}"
		done
		read -p "Number of the file you want to keep: " num_ch
		[[ $num_ch == ‘q‘ ]] && exit
		seq 0 $((${#file_choices_arry[@]}-1)) | grep -w $num_ch &>/dev/null || num_ch=0
	else
		num_ch=0
	fi
	#如果用户选择自动删除方式,则直接删除多余重复文件
	for((n=0; n<${#file_choices_arry[@]}; n++))
	do
		[[ $n -ne $num_ch ]] && {
			echo -ne "\033[1mDeleting file \" ${file_choices_arry[n]} \" ... \033[0m"
			rm -f "${file_choices_arry[n]}"
			[[ $? -eq 0 ]] && echo -e "\033[1;32mOK" || echo -e "\033[1;31mFAIL"
			echo -ne "\033[0m"
		}
	done
done	

代码下载链接

时间: 2024-11-06 23:04:05

脚本应用之一:查找并删除重复文件的相关文章

Linux查找并删除重复文件的命令行fdupes工具,dupeGuru图形工具

查了几十个网页,找到这个接近满意的解决方案http://unix.stackexchange.com/questions/146197/fdupes-delete-files-aft... 不过正则里面的叹号好像不能起到清除空行的效果,改为d;fdupes --recurse A/ B/ | sed '/^A/d; /^$/d; s/.*/"&"/' | xargs rm 但还有个小问题,如果A里面有重复的文件,但这文件不在B中,fdupes也是会列为结果,导致误删,要再想想

oracle中查找和删除重复记录的几种方法总结

平时工作中可能会遇到当试图对库表中的某一列或几列创建唯一索引时,系统提示 ORA-01452 :不能创建唯一索引,发现重复记录. 下面总结一下几种查找和删除重复记录的方法(以表CZ为例): 表CZ的结构如下: 1 SQL> desc cz 2 Name Null? Type 3 ------------------------------------------------------------------- 4 C1 NUMBER(10) 5 C10 NUMBER(5) 6 C20 VARC

fso查找被删除的文件

<html> <head> </head> <body> 源目录:<input id="txtOld" value="F:\开发\fso"></input> 新目录:<input id="txtNew"></input> 对比:<input id="btnCompare" onclick="compareFile()

python 删除重复文件 附源代码

啥也不说了,直接上源码 #! /usr/bin/env python #coding=utf-8 import os import md5 import time def getmd5( filename ): ''' 形参:文件名 返回:文件的MD5码 ''' file = open( filename, 'rb' ) file_content = file.read(1024*1024) file.close() m = md5.new( file_content ) return m.he

oracle 查找或删除重复记录的语句

--oracle查找重复记录select * from  tableA  a where a.rowid>=(select min(rowid) from tableA b where a.column=b.column) --oracle删除重复记录delete from  tableA  a where a.rowid>=(select min(rowid) from tableB b where a.column=b.column) --oracle删除重复记录(保留一条)delete

??Duplicate File Finder Pro mac(重复文件搜索软件)

?Duplicate File Finder Pro mac特别版是Mac平台上的一款好用的重复文件搜索软件,操作简单,使用方便,只需要三步就可以快速查找和删除重复文件,重复文件通常是浪费和不必要的,保持它们只是浪费宝贵的硬盘空间.Duplicate File Finder Pro mac能够轻松的为你的电脑删除隐藏着的重复文件.减轻电脑的内存空间的压力,加快运行速度. ?Duplicate File Finder Pro mac特别版下载路径:http://t.cn/AiYiK0Lw ?Dup

shell脚本之删除内容相同的重复文件

#!/bin/bash #!删除内容相同的重复文件 ls -lS --time-style=long-iso | awk 'BEGIN{ getline;getline; name1=$8;size=$5 } { name2=$8; if(size==$5) { "md5sum " name1 | getline;csum1=$1; "md5sum " name2 | getline;csum2=$2; if(csum1==csum2) { print name1;

删除重复的脚本文件

经研究发现,即便是美国排名前10位的网站,都可以犯这个错.你有什么理由说你就一定不会呢?是的,有时候可能不是你一个人的错,在一些较大的团队和较大的项目,尤其是有大量脚本的时候,可能就要特别小心地对这些脚本进行管理了. 其实要删除重复脚本,最重要的是要对脚本进行有效的管理,并且在编写页面的时候,仔细地进行引用.在ASP.NET中,善于利用一些框架,可以最大可能性地避免这个问题

windows for循环 批量查找文件并用winrar压缩并删除原文件

需求:因MSSQL2005备份无压缩功能,为节约空间对备份做压缩. 解决思路:查找备份目录下所有.bak备份文件压缩并删除原文件 命令如下: FOR /R "D:\_SQL_DATA_BACK" %f in (*.bak) DO "C:\Program Files\WinRAR\WinRAR.exe" a -tk -ep1 -m5 -df -y "%f.rar" "%f" bat脚本如下: @echo off FOR /R &