bash&shell系列文章:http://www.cnblogs.com/f-ck-need-u/p/7048359.html


要比较两个文件的内容是否完全一致,可以简单地使用diff命令。例如:

diff file1 file2 &>/dev/null;echo $?

但是diff命令只能给定两个文件参数,因此无法一次性比较多个文件(目录也被当作文件),而且diff比较非文本类文件或者极大的文件时效率极低。

这时可以使用md5sum来实现,相比diff的逐行比较,md5sum的速度快的多的多。

md5sum的使用方法见:Linux中文件MD5校验

但md5sum只能通过查看md5值来间接比较文件是否相同,要实现批量自动比较,则需要写成循环。脚本如下:

#!/bin/bash
###########################################################
# description: compare many files one time #
# author : 骏马金龙 #
# blog : http://www.cnblogs.com/f-ck-need-u/ #
########################################################### # filename: md5.sh
# Usage: $ file1 file2 file3 ... IFS=$'\n'
declare -A md5_array # If use while read loop, the array in while statement will
# auto set to null after the loop, so i use for statement
# instead the while, and so, i modify the variable IFS to
# $'\n'. # md5sum format: MD5 /path/to/file
# such as:80748c3a55b726226ad51a4bafa1c4aa /etc/fstab
for line in `md5sum "$@"`
do
index=${line%% *}
file=${line##* }
md5_array[$index]="$file ${md5_array[$index]}"
done # Traverse the md5_array
for i in ${!md5_array[@]}
do
echo -e "the same file with md5: $i\n--------------\n`echo ${md5_array[$i]}|tr ' ' '\n'`\n"
done

为了测试该脚本,先复制几个文件,并修改其中几个文件的内容,例如:

[root@xuexi ~]# for i in `seq -s' ' `;do cp -a /etc/fstab /tmp/fs$i;done
[root@xuexi ~]# echo ha >>/tmp/fs4
[root@xuexi ~]# echo haha >>/tmp/fs5

现在,/tmp目录下有6个文件fs1、fs2、fs3、fs4、fs5和fs6,其中fs4和fs5被修改,剩余4个文件内容完全相同。

[root@xuexi tmp]# ./md5.sh /tmp/fs[1-6]
the same file with md5: a612cd5d162e4620b442b0ff3474bf98
--------------------------
/tmp/fs6
/tmp/fs3
/tmp/fs2
/tmp/fs1 the same file with md5: 80748c3a55b726226ad51a4bafa1c4aa
--------------------------
/tmp/fs4 the same file with md5: 30dd43dba10521c1e94267bbd117877b
--------------------------
/tmp/fs5

更具通用性地比较方法:比较多个目录下的同名文件。

[root@xuexi tmp]# find /tmp -type f -name "fs[0-9]" -print0 | xargs -0 ./md5.sh
the same file with md5:a612cd5d162e4620b442b0ff3474bf98
--------------------------
/tmp/fs6
/tmp/fs3
/tmp/fs2
/tmp/fs1 the same file with md5:80748c3a55b726226ad51a4bafa1c4aa
--------------------------
/tmp/fs4 the same file with md5:30dd43dba10521c1e94267bbd117877b
--------------------------
/tmp/fs5

脚本说明:

(1).md5sum计算的结果格式为"MD5 /path/to/file",因此要在结果中既输出MD5值,又输出相同MD5对应的文件,考虑使用数组。

(2).一开始的时候我使用while循环,从标准输入中读取每个文件md5sum的结果。语句如下:

md5sum "$@" | while read index file;do
md5_array[$index]="$file ${md5_array[$index]}"
done

但由于管道使得while语句在子shell中执行,于是while中赋值的数组md5_array在循环结束时将失效。所以可改写为:

while read index file;do
md5_array[$index]="$file ${md5_array[$index]}"
done <<<"$(md5sum "$@")"

不过我最终还是使用了更繁琐的for循环:

IFS=$'\n'
for line in `md5sum "$@"`
do
index=${line%% *}
file=${line##* }
md5_array[$index]="$file ${md5_array[$index]}"
done

但md5sum的每行结果中有两列,而for循环采用默认的IFS会将这两列分割为两个值,因此还修改了IFS变量的值为$'\n',使得一行赋值一次变量。

(3).index和file变量是为了将md5sum的每一行结果拆分成两个变量,MD5部分作为数组的index,file作为数组变量值的一部分。因此,数组赋值语句为:

md5_array[$index]="$file ${md5_array[$index]}"

(4).数组赋值完成后,开始遍历数组。遍历的方法有多种。我采用的是遍历数组的index列表,即每行的MD5值。

# Traverse the md5_array
for i in ${!md5_array[@]}
do
echo -e "the same file with md5: $i\n--------------\n`echo ${md5_array[$i]}|tr ' ' '\n'`\n"
done

shell脚本示例:批量比较多个文件的内容是否相同的更多相关文章

  1. (转)通过shell脚本实现批量添加用户和设置随机密码以及生产环境如何批量添加

    通过shell脚本实现批量添加用户和设置随机密码以及生产环境如何批量添加 原文:http://www.21yunwei.com/archives/4773 有一个朋友问我如何批量创建用户和设置密码 , ...

  2. shell脚本:批量修改文件名

    参考链接1:shell脚本:批量修改文件名(删除文件名中字符) 参考链接2:linux shell 字符串操作详解 (长度,读取,替换,截取,连接,对比,删除,位置 ) 参考链接3:每天一个linux ...

  3. PHP批量清空删除指定文件夹内容

    PHP批量清空删除指定文件夹内容: cleancache.php <?php // 清文件缓存 $dirs = array( realpath(dirname(__FILE__) . '/../ ...

  4. shell脚本中使用echo显示带颜色的内容

    shell脚本中使用echo显示带颜色的内容,需要使用参数-e 格式如下: echo -e "\033[字背景颜色;文字颜色m字符串\033[0m" 例如: echo -e &qu ...

  5. 使用shell脚本分析Nagios的status.dat文件

    前言 Nagios的安装和配置以及批量添加监控服务器在我前面的文章中已经讲的很详细了. 我们知道,Nagios的网页控制页面(一般为http://nagio.domain.com/nagios)里可以 ...

  6. shell脚本获取文件名、路径名、文件类型

    1. 从字符串获取指定内容 从字符串中提取特定的信息,常用于获取文件名.文件类型.所在路径等. 1.1 获取字符串信息 用指定的方式(PATTERN)从字符串(PARAMETERS)中移除内容 &qu ...

  7. shell脚本仅列出当前目录下的文件及文件夹

    #!/bin/bash function ergodic(){ ` # do # "/"$file ] # then # ergodic $"/"$file # ...

  8. 利用python和shell脚本生成train.txt的标签文件

    1. 用shell脚本生成带绝对路径的train.txt 例如我要生成如下形式的带标签的文件,如图:(如有两个标签:0 和 1) shell脚本如下: 这样标签0写入了train.txt # /usr ...

  9. 【shell脚本】批量修改扩展名===modifyExtension.sh

    前提:需切换到需要批量修改扩展名的目录下,运行脚本 [root@VM_0_10_centos shellScript]# cat modifyExtension.sh #!/bin/bash # 编写 ...

随机推荐

  1. RK3288 uboot启动流程

    VS-RK3288嵌入式板卡 U-boot 启动流程小结 bl    board_init_f -> crt0.S    initcall_run_list(init_sequence_f) - ...

  2. 检测MySQL主从备份是否运行

    通过查看 slave  状态,确保 Slave_IO_Running: Yes Slave_SQL_Running: Yes #!/bin/bash#Author:Darius-Dmysql -uro ...

  3. mongdb的索引及备份

    1. mongodb的索引 1.1 为什么mongdb需要创建索引 加快查询速度 进行数据的去重 1.2 mongodb创建简单的索引方法 语法: db.集合.ensureIndex({属性:1}), ...

  4. How to setup Visual Studio without pain

    Visual Studio (VS) can be very hard to install. If you are lucky, one whole day may be enough to ins ...

  5. java面试一、1.2集合

    免责声明:     本文内容多来自网络文章,转载为个人收藏,分享知识,如有侵权,请联系博主进行删除. 1.2常见集合 List.Set.Map的区别以及选用 List和Set都继承与Collectio ...

  6. 【洛谷P3960】列队题解

    [洛谷P3960]列队题解 题目链接 题意: Sylvia 是一个热爱学习的女孩子. 前段时间,Sylvia 参加了学校的军训.众所周知,军训的时候需要站方阵. Sylvia 所在的方阵中有 n×m ...

  7. <笔记>Apache+PHP+MYSQL配置

    (1)Apache的the requested operation has failed错误: cmd—输入netstat –ano,可看到80端口已被进程占用,PID为4 打开任务管理器—〉查看—〉 ...

  8. scrapy爬虫之断点续爬和多个spider同时爬取

    from scrapy.commands import ScrapyCommand from scrapy.utils.project import get_project_settings #断点续 ...

  9. Centos6.5安装中文支持和中文输入法---VIM编辑器中文支持

    Centos6.5安装中文支持和中文输入法 第一步:中文支持:    在shell命令下输入: # vi  /etc/sysconfig/i18n 然后修改LANG="en_US.UTF-8 ...

  10. Openvswtich 学习笔记

    场景: 创建一个Virtual Switch,支持VLAN,支持MAC-Learning 包含下面四个Port: P1, truck port P2, VLAN 20 P3, P4 VLAN 30 包 ...