您现在的位置是:网站首页 -> Linux 文章内容
linux awk命令示例(摘自书本)-itarticl.cc-IT技术类文章记录&分享
发布时间: 9年前【Linux】 129人已围观【返回】
#!/bin/bash
#name:remove_one.sh
#用途:查找并删除重复文件,每个文件只保留一个样本
#将文件依据大小排序并输出
ls -lS | awk 'BEGIN {
#得到第一行total总数并丢弃,读取下一行
getline;getline;
name1=$9;size=$5;
}
{
name2=$9;
if(size==$5)
#大小一样的可能是内容相同的文件
{
#用md5进行校验和
("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
#计算重复文件的md5sum,将重复文件中的一采样写入duplicate_sample中
cat duplicate_files|xargs -I {} md5sum {}| sort | uniq -w 32 | awk '{print $2}' | sort -u > duplicate_sample
echo Removing...
#删除在duplicate_files中列出且未被duplicate_sample列出的全部文件
comm duplicate_files duplicate_sample -2 -3|tee /dev/stderr|xargs rm
echo Removed duplicates files successfully
--------------------------------------------------------
执行:
[root@node1 tmp]# sh remove_one.sh
过滤的是当前目录下的,不处理目录,不递归处理子目录
工作原理:
1. ls -lS 对当前目录下的所有文件依据大小排序并列出,这样大小接近的文件就会排列在一起.识别大小相同的文件是我们查找重复文件的第一步.接下来,计算这些文件的校验和.如果检验和相同,那么这些文件就是重复文件,并将删除.
2. 在从文件中读取文本行之前,首先要执行awk的BEGIN{}语句块.读取文件行的工作在{}语句块中进行,读取并处理完毕之后,执行END{}语句块. ls -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
3. 第一行输出告诉我们文件数量,这个信息在没例中没有什么用处,我们用getline读取第一行,然后丢弃.由于需要对每一行及其下一行来比对文件大小,因此用getline读取长文件列表的第一行,并存储文件名和大小(它们分别是第8列和第5列).这样我们就先得到了一行.接下来awk进入{}语句块(在这个语句中读取余下的文本行),读取到的每一行文本都会执行该语句块.它将当前行中读取到的文件大小与之前存储在变量size中的值进行比较.如果相等,那就意味着两个文件至少在大小上是相同的,随后再用md5sum执行进一步的检查.
4. 我们在给出的解决方案中使用了一些技巧.
4.1 在awk中,外部命令的输出可以用以下方法读取:
"cmd" | getline
随后就可以在$0中获取命令的输出,在$1,$2,...$n中获取命令输出中的每一列.我们将文件的md5sum保存在变量csum1和csum2中.变量name1和name2保存文件列表中位置连续的文件名.如果两个文件的检验和相同,那它们肯定是重复文件,其文件名会被打印出来.
4.2 我们需要从每组重复文件中找出一个文件,这样就可以删除其它副本了.计算重复文件的md5sum,从每一组重复文件中打印出其中一个.这是通过 -w 32 比较每一行的md5sum(md5sum 输出中的前32个字符,md5sum的输出通常由32个字符的散列值和文件名组成). 然后找出那些不相同的行. 这样, 每组重复文件中的一个采样被写入duplicate_sample
4.3 现在需要装饰duplicate_files中列出的且未包含在duplicate_smaple之内的全部文件删除.这些文件由comm命令负责打印出来.我们可以使用差集操作来实现.
4.4 comm通常只接受排序过的文件.所以,在重定向到duplicate_files和duplicate_sample之前,首先用sort -u 作为一个过滤器.
4.5 tee 命令在这里有一个妙用:它在将文件名传递给rm命令的同时,也起到了print的作用.tee将来自stdin的行写入文件,同时将其发送到stdout. 我们也可以将文本重定向到stderr来实现终端打印功能./dev/stderr 是对应于stderr(标准错误)的设备.通过重定向到stderr设备文件,来自stdin的文本将会以标准错误的形式出现在终端中.
4.6 awk 内建字符串处理函数
length(string): 返回字符串长度
index(string, search_string): 返回search_string在字符串中出现的位置
split(string, array, delimiter): 用定界符生成一个字符串列表,并将该列表写入数组
substr(string, start_position, end_position): 在字符串中用字符起止偏移量生成子串,并返回该子串
sub(regex, replacement_str, string): 将正则表达式匹配到的第一处内容替换成replacement_str
gsub(regex, replacement_str, string): 和sub()类似. 不过该函数会替换正则表达式匹配到的所有内容.
match(regex, string): 检查正则表达式是否能够匹配字符串. 如果能够匹配,返回非0值;否则,返回0.
发布时间: 9年前【Linux】129人已围观【返回】【回到顶端】
很赞哦! (1)
上一篇:linux sed命令
下一篇:linux awk命令
相关文章
点击排行

站长推荐

猜你喜欢
站点信息
- 建站时间:2016-04-01
- 文章统计:728条
- 文章评论:82条
- QQ群二维码:扫描二维码,互相交流
