Linux | c&cpp | Email | github | QQ群:425043908 关注本站

itarticle.cc

您现在的位置是:网站首页 -> 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年前Linux129人已围观返回回到顶端

很赞哦! (1)

上一篇:linux sed命令

下一篇:linux awk命令

文章评论

  • 请先说点什么
    热门评论
    128人参与,0条评论

站点信息

  • 建站时间:2016-04-01
  • 文章统计:728条
  • 文章评论:82条
  • QQ群二维码:扫描二维码,互相交流