重复的文件是同一个文件的多个副本,有时候,我们需要找到重复的文件,并且对其进行一些操作,我们可以结合多个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的文本会以标准错误的形式显示给终端之中

发表评论

邮箱地址不会被公开。 必填项已用*标注