【问题标题】:MD5 comparison between two text files两个文本文件之间的 MD5 比较
【发布时间】:2020-01-20 23:45:05
【问题描述】:

我刚开始学习 Linux shell 脚本。我必须在 Linux shell 脚本中比较这两个文件以获取版本控制示例:

file1.txt

  • 275caa62391ff4f3096b1e8a4975de40 苹果
  • awd6s54g64h6se4h6se45wahae654j6 球
  • e4rby1s6y4653a46h153a41bqwa54tvi 猫
  • r53aghe4354hr35a4hr65a46eeh5j45ro 脚轮

file2.txt

  • 275caa62391ff4f3096b1e8a4975de40 苹果
  • js65fg4a64zgr65f4w65ea465fa65gh7 球
  • wroghah4a65ejdtse5z4g6sa7H658aw7 蜡烛
  • wagjh54hr5ae454zrwrh354aha4564re 脚轮

如何在新添加(文件2中添加但文件1中未添加的文件)、已删除(文件2中删除但文件1中未删除的文件)和更改文件(具有相同名称但不同的校验和)? 我尝试使用 diff 、 bcompare 、 vimdiff ,但没有得到正确的文本文件输出。

提前致谢

【问题讨论】:

  • 第 3 部分(名称相同但校验和不同)--- 试试md5sum -c file1 file2
  • 第三部分他指的是正文的第一部分

标签: linux bash shell


【解决方案1】:

我不知道这样的命令是否存在,但我冒昧地在 Bash 中为您编写了一个排序机制。虽然它已经过优化,但我建议您使用自己选择的语言重新创建它。

#! /bin/bash

# Sets the array delimiter to a newline
IFS=$'\n'

# If $1 is empty, default to 'file1.txt'. Same for $2.
FILE1=${1:-file1.txt}
FILE2=${2:-file2.txt}

DELETED=()
ADDED=()
CHANGED=()

# Loop over array $1 and print content
function array_print {
        # -n creates a "pointer" to an array. This
        # way you can pass large arrays to functions.
        local -n array=$1
        echo "$1: "

        for i in "${array}"; do
                echo $i
        done
}

# This function loops over the entries in file_in and checks
# if they exist in file_tst. Unless doubles are found, a
# callback is executed.
function array_sort {
        local file_in="$1"
        local file_tst="$2"
        local callback=${3:-true}
        local -n arr0=$4
        local -n arr1=$5

        while read -r line; do

                tst_hash=$(grep -Eo '^[^ ]+' <<< "$line")
                tst_name=$(grep -Eo '[^ ]+$' <<< "$line")
                hit=$(grep $tst_name $file_tst)

                # If found, skip. Nothing is changed.
                [[ $hit != $line ]] || continue

                # Run callback
                $callback "$hit" "$line" arr0 arr1

        done < "$file_in"
}

# If tst is empty, line will be added to not_found. For file 1 this 
# means that file doesn't exist in file2, thus is deleted. Otherwise
# the file is changed.
function callback_file1 {
        local tst=$1
        local line=$2
        local -n not_found=$3
        local -n found=$4

        if [[ -z $tst ]]; then
                not_found+=($line)
        else
                found+=($line)
        fi
}

# If tst is empty, line will be added to not_found. For file 2 this
# means that file doesn't exist in file1, thus is added. Since the 
# callback for file 1 already filled all the changed files, we do 
# nothing with the fourth parameter.
function callback_file2 {
        local tst=$1
        local line=$2
        local -n not_found=$3

        if [[ -z $tst ]]; then
                not_found+=($line)
        fi
}

array_sort "$FILE1" "$FILE2" callback_file1 DELETED CHANGED 
array_sort "$FILE2" "$FILE1" callback_file2 ADDED CHANGED 

array_print ADDED
array_print DELETED
array_print CHANGED
exit 0

由于上面的代码可能很难理解,所以我把它写出来了。我希望它有所帮助:-)

while read -r line; do
       tst_hash=$(grep -Eo '^[^ ]+' <<< "$line")
       tst_name=$(grep -Eo '[^ ]+$' <<< "$line")
       hit=$(grep $tst_name $FILE2)

       # If found, skip. Nothing is changed.
       [[ $hit != $line ]] || continue

       # If name does not occur, it's deleted (exists in 
       # file1, but not in file2)
       if [[ -z $hit ]]; then
               DELETED+=($line)
       else
       # If name occurs, it's changed. Otherwise it would
       # not come here due to previous if-statement.
               CHANGED+=($line)
       fi
done < "$FILE1"

while read -r line; do
       tst_hash=$(grep -Eo '^[^ ]+' <<< "$line")
       tst_name=$(grep -Eo '[^ ]+$' <<< "$line")
       hit=$(grep $tst_name $FILE1)

       # If found, skip. Nothing is changed.
       [[ $hit != $line ]] || continue

       # If name does not occur, it's added. (exists in 
       # file2, but not in file1)
       if [[ -z $hit ]]; then
               ADDED+=($line)
       fi
done < "$FILE2"

【讨论】:

  • 看起来这个 bash 程序只比较了四行的数据,我想比较两个有很多行的文本文件。非常感谢您提供此代码。
  • @karkator 你为什么这么认为?数据取自文件,与文件长度无关。
【解决方案2】:

仅在 file1.txt 中的文件:

 awk 'NR==FNR{a[$2];next} !($2 in a)' file2.txt file1.txt > only_in_file1.txt

仅在 file2.txt 中的文件:

 awk 'NR==FNR{a[$2];next} !($2 in a)' file1.txt file2.txt > only_in_file2.txt

然后是这样的答案: awk compare columns from two files, impute values of another column

例如:

awk 'FNR==NR{a[$1]=$1;next}{print $0,a[$1]?a[$2]:"NA"}' file2.txt file1.txt  | grep NA | awk '{print $1,$2}' > md5sdiffer.txt

不过,您需要想出如何呈现这些内容。

可能有一种更优雅的方式来循环遍历最后一个示例(而不是找到具有 NA 的示例然后重新过滤),但它仍然足以关闭

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2012-03-18
    • 2011-07-12
    • 1970-01-01
    • 2016-08-20
    • 2011-08-25
    • 2019-06-19
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多