将最后修改的二进制文件复制到另一个上

时间:2015-08-12 21:23:30

标签: bash sync md5sum qnap

我想比较两个二进制文件(非常小,每个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

有什么问题?

顺便问一下,有没有更好的方法来解决这个问题?

由于

非常感谢大家的帮助。以下是脚本现在的样子。关于QNAP的QTS也有通知,但如果在其他地方运行或不需要,可以取出。

#!/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

3 个答案:

答案 0 :(得分:4)

我还建议重构这一点,既可以简化代码,又可以节省CPU周期。

#!/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内运行cpif,以便我们可以轻松检查结果。
  • 这不再使用stat了。虽然您可能永远不会超越Linux,但始终牢记可移植性始终是一个好主意,如果您可以使您的脚本可移植,那就太棒了。
  • 这不是 bash 脚本。您的脚本也不是 - 如果您使用/bin/sh调用脚本,那么您处于POSIX兼容模式,这已经使您的脚本比您想象的更加便携。 : - )
  • 缩进有帮助。您可能希望将其用于自己的脚本,以便更好地了解哪些命令与正在测试的各种条件相关联。

答案 1 :(得分: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

答案 2 :(得分:-1)

几乎就在那里。清理代码并稍微调整一下就是我得到的

sed

至少在我的机器上,您获取日期的方式是错误的。所以我重写了它。

您的哈希字符串错误。您有效地将字符串裁剪为前32个字符。通过使用md5sum,您实际上可以删除命令的第一部分,只需存储{{1}}的结果。

你也误用了HuStmpHrrr指出的条件语句。

其余的是化妆品。