学习笔记 · 2016年10月10日

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

浏览:54

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

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

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

#!/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 比对并输出了:

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