在增量发版博文里,自动识别目标文件路径是采用了标记目录特征。当部署环境多变时,会多有不便。这个替换程序,在使用时需要手动输入目标目录。当需要进一步自动化时,可以与 fint 配合使用。


  程序发布时,需要借助一个环境变量(DONATELLO_HOME),以保证函数调用的正常。

  程序目录结构

.
├── bin
│   ├── mTime    # 暂未启用
│   └── screensize    # 获取终端宽度、高度,一个C语言程序
├── lib
│   ├── displayHeader     # 设计用来打印程序头部格式,未启用
│   ├── doReplace    # 库文件,提供替换文件的函数
│   ├── findObjectFile    # 在目标路径中,寻找新文件的路径,处理多个文件的交互选择
│   ├── getscreensize     # 处理bin下C语言程序的返回结构
│   ├── printObject    # 把替换的对应关系输出到终端
│   └── progressBar    # 打印一个进度条,暂缓程序执行
└── Replace    # 主程序

  主程序 Replace:

#!/bin/bash
# Replace-1.3
# The author: donatello
# 
chkdep() {
    [ -z $1 ] && echo "Directory ?"
    [ -z $1 ] && exit 4
    [ ! -d $1 ] && echo "Without directory, please again."
    [ ! -d $1 ] && exit 6
    [ -d $1 ] && baseDirectory=$1
}
chkdep $1
# Format the "baseDirectory".
declare -g baseDirectory="$(dirname $baseDirectory)"/"$(basename $baseDirectory)"
declare -g fileName=$(ls -1R .)
declare -g -a objectFileName
declare -g -i obj=1
declare -gr father="${DONATELLO_HOME}/bin"
echo $father

clear
# Call the functions.
#. displayHeader
. ${father}/lib/findObjectFile
. ${father}/lib/printObject
. ${father}/lib/doReplace

# Define count function.
# Count the number of array elements.
count_objectFileName() {
    local -i k=${#objectFileName[@]}
    [ 1 -ge $k ] && echo -e "\t\fCheck for new files" && return 33
    return 0
}
#
findFile
#count_objectFileName && [ 33 -eq $? ] && exit 33
count_objectFileName
[ 33 -eq $? ] && exit 33
printOjectFileDirName
replaceFile
echo -e '\nShell script ends.'
# Shell script over.


  寻找目标文件 findObjectFile

#!/bin/bash
# The command that will replace the file if exists.
MV="$(which --skip-alias mv) -v"

# Check input by user when there are many file directory will be confirm.
confirmInfo() {
    #echo "k=$k"
    while true; do
        # Print files there are same name.
        if [ 1 -lt $k ]; then
            echo -e "file of the same name:\f<< $i >>"
            for((i=1; i<=k; i++)); do
            #    name=$(env basename ${file[$i]})
            #    echo -e "\tNo.$i ${name}\n"
                echo -e "\tNo.$i ${file[$i]}\n"
            done
        fi

        # Confirm file.
        while true; do
            read -p "Please confirm the path of the file that will be replace. No.-> " -N 1 confirm 1>/dev/null && echo ""
            if [ $confirm -ge 1 ] && [ $confirm -le $k ]; then
                break
            else
                echo "No's error."
            fi
        done

        # Reconfirm file.
        read -p "Do you confirm you choice ? (yY/nN)... " -N 1 reconfirm && echo ""
        if [ 'y' = $reconfirm ]; then
            clear
            break
        elif [ 'n' = $reconfirm ]; then
            echo "Please confirm again."
        else
            echo "Char's invalid."
        fi
    done
    #printf "Good luck, the file is %s.\n" "file[$confirm]"
    return $confirm
}

# Find the file that will be replaced.
findFile() {
    local -a file
    local -i k=1
    local -i confirm=0
    local -l reconfirm=n

    for i in $(echo $fileName); do # cycle: A file is looped once.
        [ ! -f $i ] && continue

        objectFileName=$(find $baseDirectory -name $i -print)
        for item in $(echo "${objectFileName}"); do
            #echo "item $k: $item"
            file[$k]=${item}
            let k=k+1
        done
        k=${#file[@]}
        #echo $i $k

        # There is no file with the same name, direct replacement.
        if [ 1 -eq $k ]; then
            objectFileName[$obj]=${file[$k]}
            let obj=obj+1
        fi
        # When the same file name exist, the user is required
        # to confirm the correct file path.

        # Call local function: confirmInfo
        if [ 1 -lt $k ]; then
            confirmInfo
            k=$?
            #echo "The file is ${file[${answer}]}"
            objectFileName[$obj]=${file[$k]}
            let obj=obj+1
        fi

    #    sleep 1
        # variable reset.
        k=1
        unset file
        # over
    done
}

echo "Will find files..."
# Over


  打印输出替换对应关系 printObject

#!/bin/bash

BASENAME=$(which --skip-alias basename)

printOjectFileDirName() {
    clear
    #. displayHeader
    echo "Print object files..."
    local -i k=${#objectFileName[@]}
    #echo "length, k=$k"
    for((i=1; i<k; i++)); do
        echo "Will move $(${BASENAME} ${objectFileName[$i]}) --->> ${objectFileName[$i]}"
    done

    . ${father}/lib/progressBar
}
# Over

  打印对象后,调用了进度条效果 progressBar

#!/bin/bash
#
declare -i cycle=1
declare -i length=15
declare -i k=0
#echo -n '-------------------------------------------------------'

printBar(){
    for((i=0; i<length; i++)); do
        echo -n '-'
    done

    printf "\r"
    for((i=0; i<cycle*length; i++)); do
            echo -n '-' && sleep 0.05
            echo -e -n '\b\' && sleep 0.05
            echo -e -n '\b-' && sleep 0.05
            echo -e -n '\b/' && sleep 0.05
            echo -e -n '\b*' && sleep 0.3
            echo -e -n '\b-'

            let k=k+1
            if [ $k -eq $length ]
            then
                    k=0
                    printf "\r"
            fi
    done
}
printBar


  替换文件 doReplace:

#!/bin/bash
MV="$(which --skip-alias mv) -v"
BASENAME=$(which --skip-alias basename)

replaceFile() {
    clear
    echo "Replace object files..."
    local -i k=${#objectFileName[@]}
    for((i=1; i<k; i++)); do
        $MV $(${BASENAME} ${objectFileName[$i]}) ${objectFileName[$i]}
    done
}
# do it
# Over