2015-08-12 3 views
1

Я хотел бы сравнить два бинарных файла (очень маленький, 100Kb каждый) и заменить самый старый с последним измененным.Скопируйте последний измененный двоичный файл по другому

Я создал простой сценарий, но я должен был бы ваша помощь, чтобы сделать это правильно работать:

#!/bin/sh 
# select the two files 
FILE1="/dir1/file1.binary" 
FILE2="/dir2/file2.binary" 

# create the hash of the two files 
HASH1="$(md5sum $FILE1 | cut -c 1-32)" 
HASH2="$(md5sum $FILE2 | cut -c 1-32)" 

# compare the two hashes 
if [ "$HASH1" == "$HASH2" ]; 

# if the two hashes are the same, exit 
then 
echo "the two files are identical" 
exit 0 

# otherwise compare which of them has been last modified 
fi 
DATE1="(stat -c %Y $FILE1)" 
DATE2="(stat -c %Y $FILE2)" 

# if FILE1 is newer than FILE2, replace FILE2 with FILE1 
if [ "${DATE1}" -gt "${DATE2}" ]; 
then 
cp $FILE1 $FILE2 
echo "${FILE2} was replaced by ${FILE1}" 

# if FILE2 is newer than FILE1, replace FILE1 with FILE2 
fi 
cp $FILE2 $FILE1 
echo "${FILE1} was replaced by ${FILE2}" 
exit 0 

Файл кажется работает (по крайней мере, если два файла идентичны), но если один файл имеет был изменен, я получаю следующую ошибку:

line 24: [: {(stat -c %Y test1)}: integer expression expected 

Что не так?

Кстати, есть ли лучший способ решить эту проблему?

Благодаря


Огромное спасибо всем за помощь. Вот как выглядит скрипт сейчас. Также есть уведомление о QTS для QNAP, но его можно вынуть, если он работает в другом месте или не нужен.

#!/bin/sh 

# select the two files 
FILE1="/dir1/file1" 
FILE2="/dir2/file2" 

# use or create a log file with timestamp of the output 
LOG="/dir1/ScriptLog.txt" 
TIMESTAMP=$(date +"%Y-%m-%d %Hh:%M") 

if [ ! -e $LOG ]; then 
    touch $LOG 
    echo "$TIMESTAMP - INFO: '$LOG' does not exists but has been created." >&2 
# else 
# echo "$TIMESTAMP - INFO: '$LOG' exists and it will be used if any change to '$FILE1' 
# or to '$FILE2' is needed." >&2 
fi 

# You can also pass the two file names as arguments for the script 
if [[ $# == 2 ]]; then 
    FILE1=$1 
    FILE2=$2 
fi 

# check if the two files exist and are regular 
if [ -f "$FILE1" -a -f "$FILE2" ]; then 

    # meanwhile compare FILE1 against FILE2 
    # if files are identical, stop there 
    if cmp "$FILE1" "$FILE2" 2>/dev/null>/dev/null; then 
     echo "$TIMESTAMP - INFO: '$FILE1' and '$FILE2' are identical." >&2 | >> $LOG 

    # if FILE1 is newer than FILE2, copy FILE1 over FILE2 
    elif [ "$FILE1" -nt "$FILE2" ]; then 
     if cp -p "$FILE1" "$FILE2"; then 
     echo "$TIMESTAMP - INFO: '$FILE1' replaced '$FILE2'." >&2 | >> $LOG 
      # if copy is successful, notify it into QTS 
      /sbin/notice_log_tool -a "$TIMESTAMP - INFO: '$FILE1' replaced '$FILE2'." --severity=5 >&2 
     else 
      echo "$TIMESTAMP - ERROR: FAILED to replace '$FILE2' with '$FILE1'." >&2 | >> $LOG 
      exit 1 
     fi 

    # if FILE1 is older than FILE2, copy FILE2 over FILE1 
    elif [ "$FILE1" -ot "$FILE2" ]; then 
     if cp -p "$FILE2" "$FILE1"; then 
      echo "$TIMESTAMP - INFO: '$FILE2' replaced '$FILE1'." >&2 | >> $LOG 
      # if copy is successful, notify it into QTS 
      /sbin/notice_log_tool -a "$TIMESTAMP - INFO: '$FILE2' replaced '$FILE1'." --severity=5 >&2 
     else 
      echo "$TIMESTAMP - ERROR: FAILED to replace '$FILE2' with '$FILE1'." >&2 | >> $LOG 
      exit 1 
     fi 

    # if two files are not identical but with same modification date 
    else 
     echo "$TIMESTAMP - ERROR: We should never reach this point. Something is wrong in the script." >&2 | >> $LOG 
     exit 1 
    fi 

    # if one file does not exist or is not valid, exit 
else 
    echo "$TIMESTAMP - ERROR: One of the files does not exist, has been moved or renamed." >&2 | >> $LOG 
     # if error, notify it into QTS 
     /sbin/notice_log_tool -a "$TIMESTAMP - ERROR: One of the files does not exist, has been moved or renamed." --severity=5 >&2 
    exit 1 
fi 
+0

Вам даже не нужен md5. '-gt' сравнивает число, как указано. вам нужно использовать '['$ {DATE1}" \> "$ {DATE2}"] 'или' [["$ {DATE1}"> "$ {DATE2}"]] ' – HuStmpHrrr

+0

, который вы никогда не выполняли' stat() '. вы просто определили пару строк, которые имеют символы '(', 's',' t' и т. д. в них –

+0

HuStmpHrrr, в локальном согласии, что md5 не требуется Конечно, если этот процесс будет выполняться между двумя удаленными папками, чтобы избежать несоответствия времени, потребуется проверка md5 (на локальных машинах). Правильно ли это? – giopas

ответ

4

Я также собираюсь предложить рефакторинг, как для упрощения кода, так и для сохранения ваших циклов процессора.

#!/bin/sh 

# If both files exist....  
if [ -f "$1" -a -f "$2" ]; then 

    # If they have the same content... 
    if cmp "$1" "$2" >/dev/null 2>/dev/null; then 
    echo "INFO: These two files are identical." >&2 

    # If one is newer than the other... 
    elif [ "$1" -nt "$2" ]; then 
    if cp -p "$1" "$2"; then 
     echo "INFO: Replaced file '$2' with '$1'." >&2 
    else 
     echo "ERROR: FAILED to replace file." >&2 
     exit 1 
    fi 

    # If the other is newer than the one... 
    elif [ "$1" -ot "$2" ]; then 
    if cp -p "$2" "$1"; then 
     echo "INFO: Replaced file '$1' with '$2'." >&2 
    else 
     echo "ERROR: FAILED to replace file." >&2 
     exit 1 
    fi 

    else 
    echo "ERROR: we should never reach this point. Something is wrong." >&2 
    exit 1 

    fi 

else 

    echo "ERROR: One of these files does not exist." >&2 
    exit 1 

fi 

Несколько вещей, которые могут вам пригодиться.

  • Это позволяет избежать вычисления md5 для каждого из файлов. В то время как сравнение сумм может быть прекрасным для небольших файлов, подобных вашим, становится очень дорогостоящим по мере роста ваших файлов. И это совершенно не нужно, потому что у вас есть команда cmp. Лучше привыкнуть писать код, который будет работать с меньшими изменениями, когда вы переработаете его для следующего проекта.
  • Оператор if выполняет команду, обычно [ или [[, но это может быть любая команда. Здесь мы запускаем cmp и cp в пределах if, чтобы мы могли легко проверить результаты.
  • Это не используется stat.Хотя возможно, что вы никогда не сможете смотреть за пределы Linux, всегда полезно помнить о переносимости, и если вы можете сделать свой сценарий переносимым, это здорово.
  • Это не bash сценарий. Также не был ваш скрипт - если вы вызываете свой скрипт с /bin/sh, то вы находитесь в режиме совместимости с POSIX, который уже делает это более портативным, чем вы думали. :-)
  • Отступы помогают. Возможно, вы захотите принять его для своих собственных скриптов, чтобы вы могли лучше визуально понять, какие команды связаны с различными условиями, которые проверяются.
+0

Большое вам спасибо, ghoti. Что это означает выражения «-a -f» и «-nt»? – giopas

+0

@giopas, вы можете ['man test'] (https://www.freebsd.org/cgi/man.cgi?query=test), чтобы просмотреть различные параметры команды' ['. В частности, '-a' означает« и », поэтому он объединяет« -f »$ 1« и »-f» $ 2 "'. Опция '-nt' означает« более новая, чем », поэтому вы можете проверить, является ли один файл более новым или старше другого справа от оболочки, без необходимости называть« stat »или любой другой внешний инструмент. – ghoti

+0

Спасибо, ghoti, я прочитал ваш скрипт, чтобы сделать его более понятным (для меня). Одна вещь, проверяя скрипт (версия, которую я сделал) на два фиктивных текстовых файла, получаю следующий вывод: «test1 test2 different: char 32, line 3 INFO: test2 заменен test1." Кажется, что сценарий отлично работает, но мне интересно понять, как/почему я получаю первую строку. Вы можете помочь? – giopas

0

Как насчет чего-то более простого, чем следующего?

#!/bin/sh 
# select the two files from cli 
# $1 = current file 
# $2 = new file 
FILE1=$1 
FILE2=$2 

# otherwise compare which of them has been last modified 
DATE1=`(stat -c %Y $FILE1)` 
DATE2=`(stat -c %Y $FILE2)` 

if [ $DATE2 -gt $DATE1 ]; then 
    echo "cp -f $FILE2 $FILE1" 
# cp -f $FILE2 $FILE1 
fi 
-1

Практически там. Очистка кода и настройки его немного здесь является то, что я получил

#!/bin/bash 

# select the two files (default option) 
FILE1="/dir1/file1.binary" 
FILE2="/dir1/file2.binary" 

# You can also pass the two file names as arguments for the script 
if [ $# -eq 2 ]; then 
    FILE1=$1 
    FILE2=$2 
fi 

# create the hash of the two files 
HASH1="$(md5sum $FILE1 | sed -n -e 's/^.*= //p')" 
HASH2="$(md5sum $FILE2 | sed -n -e 's/^.*= //p')" 

# get the dates of last modification 
DATE1="$(stat -f '%m%t%Sm' $FILE1 | cut -c 1-10)" 
DATE2="$(stat -f '%m%t%Sm' $FILE2 | cut -c 1-10)" 

# Uncomment to see the values 
#echo $FILE1 ' = hash: ' $HASH1 ' date: ' $DATE1 
#echo $FILE2 ' = hash: ' $HASH2 ' date: ' $DATE2 

# compare the two hashes 
if [ $HASH1 == $HASH2 ]; then 
    # if the two hashes are the same, exit 
    echo "the two files are identical" 
    exit 0 
fi 

# compare the dates 
if [ $DATE1 -gt $DATE2 ]; then 
    # if FILE1 is newer than FILE2, replace FILE2 with FILE1 
    cp $FILE1 $FILE2 
    echo "${FILE2} was replaced by ${FILE1}" 
elif [ $DATE1 -lt $DATE2 ]; then 
    # else if FILE2 is newer than FILE1, replace FILE1 with FILE2 
    cp $FILE2 $FILE1 
    echo "${FILE1} was replaced by ${FILE2}" 
else 
    # else the files are identical 
    echo "the two files are identical" 
fi 

Ваш способ получить дату не так, по крайней мере, на моей машине. Поэтому я переписал его.

Ваша строка хеша была неправильной. Вы эффективно обрезали строку до первых 32 символов. Используя sed, вы можете фактически избавиться от первой части команды и просто сохранить результат md5sum.

Вы также неправильно использовали условные утверждения, как указал HuStmpHrrr.

Остальное - косметика.

+0

Спасибо, вынимая хеш и названия разделов, кажется правильной версией моего скрипта :) – giopas

+0

Это не сработает. '[[' - это только тест, основанный только на bash, и это не скрипт bash. – ghoti

+0

gothi, вы правы в характере сценария. На самом деле ваша синтаксически лучше и теоретически быстрее (хотя размер файлов настолько мал, что преимущества, вероятно, минимальны). Тем не менее, пользователь, не являющийся экспертом, вашему решению может быть сложно прочитать и понять вашу версию. Я предпочитал читаемость производительности - в целом, я бы просто предпочел вашу версию :) – user1472709

Смежные вопросы