#!/bin/bash
#查找并删除重复文件 每个文件只保留一份
# ls -lS(-l list -S Sort files by size) --time-style指定日期和时间输出格式
# awk 从管道读取ls -lS的输出,对行列进行比较从而找出重复文件
# 执行 awk BEGIN{}语句快,读取文本行工作在{}中
# 文件ls后输出的格式为类似这种
# total 16
# -rw-r--r-- 1 slynux slynux 5 2010-06-29 11:50 other
# -rw-r--r-- 1 slynux slynux 6 2010-06-29 11:50 test
# -rw-r--r-- 1 slynux slynux 6 2010-06-29 11:50 test_copy1
# -rw-r--r-- 1 slynux slynux 6 2010-06-29 11:50 test_copy2
# 则getline得到第一行后丢弃,然后用getline读取
# 第二行储存第5列的文件大小和第八列的文件名
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=$1;
if ( csum1==csum2 )
{
print name1; print name2
}
};
size=$5; name1=name2;
}' | sort -u > duplicate_files
#中间的{}语句块读取第二行之后的内容 读取到的每一行都存文件名,然后比对文件大小
#如果一样则用md5算法比对文件名 将文件计算得到的md5值保存在csum1中
#"md5sum " name1 | getline 将md5值输出到stdout,然后 csum1=$1;从stdout读取存储到csum中
#由于第一步按照文件大小排序,若此时md5值相等的话则肯定为重复文件 输出重复的文件名
#sort按字典排序 -u 不重复输出到duplicate_files中
cat duplicate_files | xargs -I {} md5sum {} | sort | uniq -w 32 | awk '{ print "^"$2"$" }' | sort -u > duplicate_sample
#xargs 使用-I指定一个替换字符串{},这个字符串在xargs扩展时会被替换掉
#该句将重复的文件中的一个采样写入duplicate_sample中
echo Removing..
comm duplicate_files duplicate_sample -2 -3 | tee /dev/stderr | xargs rm
#求差集:打印出那些互不包含的行 打印出到终端同时重定向到文件 /dev/stderr中通过xargs处理传递给rm命令
echo Removed duplicates files successfully.
这是我百度到的一个删除文件夹中相同文件的一个脚本代码,其中他主要流程就是:
1,现将文件夹中的文件通过ls -lS 按文件大小排序,
2,其次用akw 'begin {}{}'实现文件与文件之间的对比,对比是通过md5sum 把该文件生成一个密钥,由于文件内容相同会生成相同密钥的原理,进行密钥对比从而判断是否相同,如果相同就将该相同的文件名输入到一个变量duplicate_files中,
3.将duplicate_files输出,然后继续用md5sum加密(加密后是32个字符),接着排序,然后用过uniq -w 32 取得在duplicate_files中不同的数据,比如 在duplicate_files中,a.txt,aa.txt,aaa.txt是相同文件,b.txt,bb.txt,bbb.txt是相同的,uniq -w 32 就会出去相同的,留下a.txt 和 b.txt 。然后通过awk '{ print "^"$2"$" }' 获取到文件的名字,输出到duplicate_sample中,
4.通过comm 来比较 duplicate_files duplicate_sample的差集,获取duplicate_files存在,duplicate_sample不存在的文件名,然后删除。
在这脚本中需要了解的知识点主要是:awk的用法,getline读取某行让 然后丢弃,md5sum加密,uniq。从脚本的实践中也确实能取得删除文件的效果,但是依旧存在着问题,
由于他的主流程是通过,某一个文件和下一个文件进行比较,若相同就记录,比且删除,若存在这样一个问题,a.txt b.txt .c.txt 他们文件大小相同,但是a.txt 内容和c.txt相同,但是b和他们不相同。排列顺序是 a,b,c,那就会出现的问题是,a先和b做比较,发现不同,然后在拿b和c做比较,发现也不同,但是a没有和c做比较,因此就无法盘查出相同文件,这也是这个脚本的bug。
解决的思路:由于删除相同文件,最核心的点在于,md5sum 加密后的判断,那最简单的就是,将所有的文件都先md5sum加密,然后输出给一个变量,接着用uniq去找出不同的加密,然后输出给一个新的变量,最后用comm 比较差集,找出相同的文件,接着删除。也不会存在实例代码中的问题。
网友评论