MD5 сравнение между двумя текстовыми файлами - PullRequest
1 голос
/ 20 января 2020

Я только начал изучать Linux сценарии оболочки. Я должен сравнить эти два файла в сценариях оболочки Linux для примера контроля версий:

file1.txt

  • 275caa62391ff4f3096b1e8a4975de40 apple
  • awd6s54g64h6se4h6se45wahae84j6 1009 * e4rby1s6y4653a46h153a41bqwa54tvi кошка

file2.txt

  • 275caa62391ff4f3096b1e8a4975de40 яблоко
  • wagjh54hr5ae454zrwrh354aha4564re castor

Как отсортировать эти текстовые файлы во вновь добавленные (те, которые добавляются в файл 2, но не в файл 1), удаленные (те, которые удаляются в файл 2, но не в файле 1) и измененные файлы (имеют одинаковое имя, но разные контрольные суммы)? Я пытался использовать diff, bcompare, vimdiff, но я не получаю правильный вывод в виде текстового файла.

Заранее спасибо

Ответы [ 2 ]

0 голосов
/ 20 января 2020

Файлы, которые есть только в 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 сравнить столбцы из двух файлов, вмененные значения другого столбца

например:

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

Вам нужно будет придумать, как вы хотите их представить.

Возможно, существует более элегантный способ для l oop, хотя в последнем примере (в отличие от поиска с NA и повторной фильтрации), однако этого все же достаточно, чтобы go отключить

0 голосов
/ 20 января 2020

Я не знаю, существует ли такая команда, но я позволил себе написать механизм сортировки в 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"
...