2017-01-09 8 views
0

В принципе, у меня есть 2 копии набора CSV-файлов в отдельных каталогах. 1 копия - сегодняшние данные, а другая - вчерашние данные. Сценарий, который у меня есть, делает резервное копирование только один раз в день, так что часто мне это нужно для запуска. То, что я хочу сделать, это сравнить их, чтобы проверить, совпадают ли файлы, и если в течение 14 дней один и тот же набор файлов был таким же, а затем отправляйте уведомление по электронной почте, уведомляя меня и моих коллег о том, что конкретный файл hasn ' t изменено.Мне нужно сравнить файлы в 2 каталогах и уметь определять, как долго каждый набор файлов был одинаковым в Bash

Итак, я уже получил сравнения часть вниз:

дифф DIR_1 DIR_2 кв | sort> compare_results.txt

Однако, теперь я хочу прочитать файл и иметь счетчик для каждой строки, чтобы я знал, сколько дней каждый набор файлов был одинаковым, с выходом в отдельных столбцах.

В идеале, 3 столбца будут $ name_of_file | файлы одинаковые? | сколько дней они были одинаковыми?

У меня есть время цикла начала для чтения каждой строки, но я не уверен, как прогресс:

в то время как линия чтения; сделать

counter=0 
    if [[ $line == *"not identical"* ]] 
    then 
     $something 
    else 
     ((counter += 1)) 
     $something_else 
    done < comparison_results.txt 

В случае необходимости, я могу написать весь этот вывод в файл, а затем прочитать файл, и если столбец счетчика имеет какие-либо 14s или выше, а затем отправить уведомление по электронной почте.

По существу, мой вопрос состоит в том, как читать каждую строку и отправлять ее в файл с тремя столбцами, а затем с уведомлением по электронной почте, если какой-либо из файлов был таким же в течение 14 дней или более?

+0

... но если у вас есть * актуальный вопрос *, я бы предложил попытаться извлечь его и сделать его более понятным. См. Также http://stackoverflow.com/help/how-to-ask, и особенно http://stackoverflow.com/help/mcve –

+0

Лично, кстати, я бы подумал о отслеживании отметки времени в эпоху-времени для первого было обнаружено, что два файла были одинаковыми и просто проверяли случаи, когда эта метка времени больше (14 * 3600) секунд назад. Таким образом, вы не имеете дело со счетчиком, и ваш сценарий может быть повторно запущен кучей раз в тот же день, не нарушая логики (аналогично, логика не будет нарушена, пропуская день и т. Д.). –

+0

Я редактировал сообщение, чтобы помочь прояснить вопрос. Мне нужен только сценарий для запуска один раз в день, поэтому я не уверен, что временная метка будет необходима. Если, конечно, это было бы проще в обращении, чем счетчик. –

ответ

0

Вот приблизительный вариант того, что может выглядеть функция для этой цели. Обратите внимание, что я пишу только имена (в eval -safe quoteed form) файлов, которые были идентичны дольше, чем minAge секунд. Отправка электронной почты - это упражнение для читателя.

findConsistentlyIdenticalFiles() { 
    local dirA=$1 dirB=$2 storeLoc=$3 minAge=$4 
    local fnA fnB fnStore fn currentTime storedTime 

    mkdir -p -- "$storeLoc" || return 

    # in very new bash, faster alternative is: printf -v currentTime '%(%s)T' -1 
    # ...the following command using date is the older/slower/compatible alternative: 
    currentTime=$(date +%s) 

    # for each file in dirA... 
    while IFS= read -r -d '' fnA; do 

    # strip the directory name... 
    fn="${fnA#$dirA}"; fn="${fn#/}" 

    # and calculate the name of a corresponding file in dirB 
    fnB=${dirB}/${fn} 

    # if a file in dirA doesn't exist in dirB, or the dirB copy differs, clear our flag 
    if [[ ! -e $fnB ]] || ! cmp -s "$fnA" "$fnB"; then 
     rm -f -- "$storeLoc/$fn" 
     continue 
    fi 

    fnStore=$storeLoc/$fn 
    if [[ -e $fnStore ]]; then 
     # if we already have a marker, check whether it's over minAge seconds old 
     storedTime=$(<"$fnStore") 
     if ((storedTime < currentTime - minAge)); then 
     printf '%q\n' "$fn" 
     fi 
    else 
     # whereas if we don't have a marker, populate it with the current time 
     mkdir -p -- "${fnStore%/*}" 
     printf '%s\n' "$currentTime" >"$storeLoc/$fn" 
    fi 
    done < <(find "$dirA" -type f -print0) 

    # ...also, prune any store contents that don't have corresponding dirA contents 
    while IFS= read -r -d '' fnStore; do 
    fn="${fnStore#$storeLoc}"; fn="${fn#/}" 
    [[ -e $dirA/$fn ]] || rm -f -- "$fnStore" 
    done < <(find "$storeLoc" -type f -print0) 
} 

Используется как:

findConsistentlyIdenticalFiles dirA dirB .cmptimes "$((3600 * 14))" 

Очевидно, что вы можете легко проверить логику, используя гораздо меньшее количество секунд (60 найти одинаковые файлы, которые не изменялись в течение последней минуты, 5 за последние 5 секунды и т. д.).


Некоторые примечания:

  • Использование find -print0 испускает NUL-разделителями список имен файлов и IFS= read -r -d '' filename считывает одно имя из такого NUL-разделителями списка. Этот формат гарантированно корректно обрабатывается даже с очень необычными или даже злонамеренными именами - именами с новыми символами, именами, содержащими строки, которые выглядят как вывод diff -sq и т. Д. См. BashFAQ #1 и UsingFind.
  • Синтаксис < <(find ...) исключает проблему, описанную в BashFAQ #24, где трубопровод от find в цикл создает подоболочку, из которой не удается выйти из локального состояния оболочки.
  • Формат - это один файл метаданных в файле содержимого.Это упрощает чтение, запись или обновление определенного контента, а не чтение и запись всего файла за раз.
  • Синтаксис, используемый для разметки компонентов из названий каталогов (то есть ${fn#$dirA}, ${fn#/}) - parameter expansion.
  • Приведено цитирование справа от назначений, чтобы сделать подсветку синтаксиса StackOverflow счастливой и не связан с правильностью.