将最后修改的二进制文件复制到另一个文件上
Copy last modified binary file over the other one
我想比较两个二进制文件(非常小,每个 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=
FILE2=
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
像下面这样简单一点的怎么样?
#!/bin/sh
# select the two files from cli
# = current file
# = new file
FILE1=
FILE2=
# 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
快到了。清理你的代码并稍微调整一下,这就是我得到的
#!/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=
FILE2=
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 指出的那样,您还误用了条件语句。
剩下的就是化妆品了。
我还建议重构它,以简化代码并节省您的 CPU 周期。
#!/bin/sh
# If both files exist....
if [ -f "" -a -f "" ]; then
# If they have the same content...
if cmp "" "" >/dev/null 2>/dev/null; then
echo "INFO: These two files are identical." >&2
# If one is newer than the other...
elif [ "" -nt "" ]; then
if cp -p "" ""; then
echo "INFO: Replaced file '' with ''." >&2
else
echo "ERROR: FAILED to replace file." >&2
exit 1
fi
# If the other is newer than the one...
elif [ "" -ot "" ]; then
if cp -p "" ""; then
echo "INFO: Replaced file '' with ''." >&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
语句运行一个命令,通常是[
或[[
,但它可以是任何命令。在这里,我们在 if
中 运行 cmp
和 cp
,以便我们可以轻松检查结果。
- 这不再使用
stat
。虽然您可能永远不会超越 Linux,但牢记可移植性始终是个好主意,如果您可以使脚本可移植,那就太好了。
- 这不是 bash 脚本。你的脚本也不是——如果你用
/bin/sh
调用你的脚本,那么你就处于 POSIX 兼容模式,这已经使它比你想象的更便携。 :-)
- 缩进有帮助。您可能希望将它用于您自己的脚本,以便您可以更好地了解哪些命令与正在测试的各种条件相关联。
我想比较两个二进制文件(非常小,每个 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=
FILE2=
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
像下面这样简单一点的怎么样?
#!/bin/sh
# select the two files from cli
# = current file
# = new file
FILE1=
FILE2=
# 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
快到了。清理你的代码并稍微调整一下,这就是我得到的
#!/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=
FILE2=
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 指出的那样,您还误用了条件语句。
剩下的就是化妆品了。
我还建议重构它,以简化代码并节省您的 CPU 周期。
#!/bin/sh
# If both files exist....
if [ -f "" -a -f "" ]; then
# If they have the same content...
if cmp "" "" >/dev/null 2>/dev/null; then
echo "INFO: These two files are identical." >&2
# If one is newer than the other...
elif [ "" -nt "" ]; then
if cp -p "" ""; then
echo "INFO: Replaced file '' with ''." >&2
else
echo "ERROR: FAILED to replace file." >&2
exit 1
fi
# If the other is newer than the one...
elif [ "" -ot "" ]; then
if cp -p "" ""; then
echo "INFO: Replaced file '' with ''." >&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
语句运行一个命令,通常是[
或[[
,但它可以是任何命令。在这里,我们在if
中 运行cmp
和cp
,以便我们可以轻松检查结果。 - 这不再使用
stat
。虽然您可能永远不会超越 Linux,但牢记可移植性始终是个好主意,如果您可以使脚本可移植,那就太好了。 - 这不是 bash 脚本。你的脚本也不是——如果你用
/bin/sh
调用你的脚本,那么你就处于 POSIX 兼容模式,这已经使它比你想象的更便携。 :-) - 缩进有帮助。您可能希望将它用于您自己的脚本,以便您可以更好地了解哪些命令与正在测试的各种条件相关联。