shell 编写文件和文件夹拷贝函数

在 shell 终端拷贝文件夹和文件,是很简单的事情,直接 cp -arf 就搞定了。但是在自动化 shell 脚本中,可能会出现种种原因而导致拷贝失败或拷贝不全的情况,出问题的时候也无法核对是否拷贝成功,这时候黑锅就来了……

若想不背锅或快速排查问题,在拷贝文件夹或文件后进行文件核对并输出结果,就显得尤其重要。

首先,编写一个函数脚本( REPLACE_FILES.sh ):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
#!/usr/bin/env bash
set -e

#替换文件夹内容
REPLACE_DIR(){
#获取源文件夹和目标文件夹
local DIR1=${1}
local DIR2=${2}
#创建目标文件夹
mkdir -p ${DIR2}

#拷贝源文件夹的文件到目标文件夹
set -x
cp -arf ${DIR1}/* ${DIR2}
set +x

#进行文件对比验证
#统计源文件夹文件名及md5信息并赋值
cd ${DIR1}
DIR1_MD5S=`find . -type f -exec md5sum {} \;`
DIR1_FILES=`find . -type f`
#获取文件夹名
DIR_NAME=`basename ${DIR2}`

#轮询比对
#当存在源目录的文件
for X in ${DIR1_FILES}
do
#获取文件MD5
DIR1_MD5=`echo "${DIR1_MD5S}"|grep "${X}"|grep -v "${X}."|awk '{print $1}'`
#获取目标目录对应文件的MD5
cd ${DIR2}
DIR2_MD5=`find . -type f -wholename "${X}" -exec md5sum {} \;|awk '{print $1}'`

#MD5比对
if [[ ${DIR1_MD5} == ${DIR2_MD5} ]]; then
echo -e "\n${DIR1_MD5}\n${DIR2_MD5}\n"
echo -e "\nREPLACE ${X} COMPLETE!\n"
else
echo -e "\n${DIR1_MD5}\n${DIR2_MD5}\n"
echo -e "\nREPLACE ${X} FAIL!\n"
exit 1
fi
done
echo -e "\nDIR ${DIR_NAME} REPLACE COMPLETE!\n"
}

#替换文件
REPLACE_FILE(){
#定义源文件和目标文件
local FILE1=${1}
local FILE2=${2}

#拷贝并替换文件
set -x
cp -af ${FILE1} ${FILE2}
set +x

#或者双方MD5值并进行比对
FILE1_MD5=`md5sum ${FILE1}|awk '{print $1}'`
FILE2_MD5=`md5sum ${FILE2}|awk '{print $1}'`
FILE_NAME=`echo "${FILE2}"|awk -F "/" '{print $NF}'`
if [[ ${FILE1_MD5} == ${FILE2_MD5} ]]; then
echo -e "\n${FILE1_MD5}\n${FILE2_MD5}\n"
echo -e "\n${FILE_NAME} REPLACE COMPLETE!\n"
else
echo -e "\n${FILE1_MD5}\n${FILE2_MD5}\n"
echo -e "\n${FILE_NAME} REPLACE FAIL!\n"
return 1
fi
}

然后调用此脚本内的函数,就能实现 MD5 比对并输出了:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
#!/usr/bin/env bash
set -e;
cd `dirname $0`

#所有变量均在ENV.sh定义

. ./ENV.sh
. ./REPLACE_FILES.sh

DO_REPLACE_DIR(){
#支持多个文件夹循环替换,变量命名为(RELEASE_DIR,RELEASE_DIR2,RELEASE_DIR3...)(SRC_DIR,SRC_DIR2,SRC_DIR3...)
FCT=`cat ../env/${ENV}.sh|grep "readonly RELEASE_DIR"|wc -l`
for (( i = 1; i <= ${FCT}; i++ )); do
RELEASE_DIR1=${RELEASE_DIR}
SRC_DIR1=${SRC_DIR}
eval DIR1=\${RELEASE_DIR${i}}
eval DIR2=\${SRC_DIR${i}}
REPLACE_DIR ${DIR1} ${DIR2}
done
}

DO_REPLACE_FILE(){
#支持多个文件循环替换,变量命名为(RELEASE_FILE,RELEASE_FILE2,RELEASE_FILE3...)(SRC_FILE,SRC_FILE2,SRC_FILE3...)
FCT=`cat ../env/${ENV}.sh|grep "readonly RELEASE_FILE"|wc -l`
for (( i = 1; i <= ${FCT}; i++ )); do
RELEASE_FILE1=${RELEASE_FILE}
SRC_FILE1=${SRC_FILE}
eval FILE1=\${RELEASE_FILE${i}}
eval FILE2=\${SRC_FILE${i}}
REPLACE_FILE ${FILE1} ${FILE2}
done
}

DO_REPLACE_DIR
DO_REPLACE_FILE