重复的文件是同一个文件的多个副本,有时候,我们需要找到重复的文件,并且对其进行一些操作,我们可以结合多个shell工具去完成这项任务
首先,我们先创建一些测试方法
echo “Hello” > test;
cp test test_copy1;.
cp test test_copy2;
那么如何对其进行操作,会有一个如下的脚本帮助我们做这件事,利用了md5值相同的原因
#!/bin/bash
#用于查找并删除重复文件,每个文件只保存一样 ls -lS | 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 cat duplicate_files |xargs -I {} md5sum {} | sort | uniq -w 32 | awk ‘{print “^”$2″$”}’ | sort -u > duplicate_sample echo Removing.. comm duplicate_files duplicate_sample -2 -3| tee /dev/stderr |xargs rm echo Removed is succsess |
然后直接使用脚本就可以了
整个脚本的工作原理为
找到某一个目录中同一个文件的所有副本,然后保留单个副本的同时删除其他的副本
ls -lS 让文件按照大小进行排序后输出
awk进行读取输出,然后进行比较,找出重复文件
具体的操作如下:
1.首先,我们将文件按照大小的排序方式进行列出,这样大小接近的文件就会排列在一起,识别大小相同的文件,是第一步,然后计算md5的和,md5相同,就可以删除
首先会执行awk的BEGIN{}语句块,然后读取文本行的工作在{}语句块中进行,读取并处理完成所有的行,执行END{}语句,ls -lS的输出如下
首先是第一行,因为是打印文本数量,所以基本没啥用处,然后我们直接getline,获取到这行,并进行丢弃
然后对每一行以及下一行进行对比,我们一次的多去每一行及其下一行来进行文件大小对比,因此getline读取长文件列表的第一行,并存储文件名和大小,这样我们就提取到了一行,awk进入{}语句块,对于读取到的每一行,都会执行这个语句块,将从当前行中读取到,然后将当前行中读取到的文件和之前存储在变量size中的值进行比较,如果相同,就进行下一步的比较,利用md5sum执行进一步的检查
awk中,外部命令的输出可以用下面的方法读取
“cmd” | getline
随后,我们从$0获取命令的输出,在$1,$2,…$n获取命令输出中的每一行,然后将md5sum保存在变量csum1 csum2中,变量name1 name2保存文件列表中位置连续中的文件名,两个文件的校验相同了,就可以认为是重复文件
我们需要从每组重复文件中找到一个文件,并且保留一个副本,能够删除其他的重复的文件,我们计算重复文件的md5sum,从每一组重复文件之中打印出一个文件,然后通过-w 32比较每一行的md5sum,输出通常由32个字符的散列表和文件名组成,然后找到那些不相同的行,因此,每组重复的文件的一个采样就被写入 duplicate_sample
现在将duplicate_files中累出的且未被列于duplicate_sample之内的全部文件删除,comm命令打印出来并且duplicate_sample之前,我们首先用sort -u作为一个过滤器
tee这里作为一个作用,将文件名传递给rm命令的同事,起到了print的功能,tee将来自stdin的行写入文件,并且将其发送到stdout,我们将文本重定向到stderr来实现终端打印功能 /dev/stderr是对应stderr标准错误的设备,我们将输出定向给这个设备,来自stdin的文本会以标准错误的形式显示给终端之中