การเขียนโปรแกรมเชลล์ (8)

รายละเอียดของโปรแกรม copydir

ต้นแบบของ copydir
#!/bin/sh

if [ $# -ne 2 ] ;then
    echo "Usage : $0 [source dir] [dest dir]"
    exit 1
fi

if [ ! -d $1 ] ;then
    echo "\"$1\" must be a directory, please check."
    exit 1
fi

if [ ! -w $2 ] ;then
    if [ ! -a $2 ] ;then
        echo -n "\"$2\" does not exist, do you want to create it? [y/n] :"
	read ans
  	while [ true ] ;do
	    case "$ans" in
	    y|Y|yes|YES) 
	        mkdir $2
		if [ $? -ne 0 ] ;then
		    echo "Write \"$2\" error"
		    exit 1
		fi
		break ;;
	    n|N|no|NO)
		echo "Ok, don't creat directory, so this will done nothing."
		exit 0 ;;
	    *)
		echo -n "Expect \"yes\" or \"no\", please answer [y/n] :"
		read ans
	    esac
	done
    else
        echo "\"$2\" does not have write permission, please check."
        exit 1
    fi
else
    if [ ! -d $2 ] ;then
        echo "\"$2\" is not a directory, please check."
        exit 1
    fi
fi

LISTFILE=`ls $2`
if [ ! -z "$LISTFILE" ] ;then
    echo -n "There is some file in \"$2\", still process copy directory? [y/n] :"
    ans=""
    read ans
    while [ true ] ;do
        case "$ans" in
        y|Y|yes|YES) 
            break ;;
        n|N|no|NO)
	    echo "Ok, don't process, so this will done nothing."
	    exit 0 ;;
	*)
	    echo -n "Expect \"yes\" or \"no\", please answer [y/n] :"
	    read ans
	esac
    done
fi

SOURCEPARDIR=`dirname $1`
SOURCENAME=`basename $1`
DESTPARDIR=`dirname $2`
DESTNAME=`basename $2`
CURRDIR=`pwd`

echo "Copy in process..."
cd $1
if [ $DESTPARDIR = "." ] ;then
    # Destination is relative reference
    find -print | cpio -pd $CURRDIR/$DESTNAME
else
    # Destination is full reference
    find -print | cpio -pd $DESTPARDIR/$DESTNAME
fi
cd $CURRDIR
echo "Copy directory complete."
exit 0
อธิบายโปรแกรม

copydir ฉบับปรับปรุง

จะเห็นว่าโปรแกรม copydir ของเรานั้นมีการทำงานอยู่ขั้นตอนหนึ่งที่ซ้ำซ้อนกันอยู่ซึ่งก็คือขั้นตอนของการสอบถามและรับคำตอบยืนยัน ซึ่งขั้นตอนนี้จะถูกนำมาใช้สองครั้งคือการถามว่าต้องการจะสร้างไดเรกทอรีปลายทางหรือไม่ และถามว่าจะยังต้องการทำขั้นตอนของการสำเนาไดเรกทอรีอยู่หรือไม่ในกรณีที่มีไฟล์อยู่ในไดเรกทอรีปลายทางจะเห็นว่าถ้าเราสามารถแยกขั้นตอนการถามตอบนี้ออกมาเป็นฟังก์ชั่นต่างหาก จะทำให้เราไม่ต้องเขียนโปรแกรมซับซ้อน และจะทำให้โปรแกรมสามารถอ่านและแก้ไขได้ง่ายขึ้นนอกจากนี้หากเราเขียนโปรแกรมเชลล์อื่นๆและต้องการใช้ขั้นตอนการทำงานในลักษณะนี้เราก็จะสามารถนำเอาฟังก์ชั่นนี้ไปใช้งานด้วยได้

สำหรับฟังก์ชั่นการถามตอบนี้ ควรมีการรับพารามิเตอร์ที่เป็นข้อความที่ต้องการจะให้โปรแกรมพิมพ์ออกมาเป็นคำถาม เพื่อที่เราสามารถจะใช้โปรแกรมนี้กับการถามคำถามแบบต่างๆได้ และเมื่อผู้ใช้ใส่ข้อมูลมาในลักษณะตอบรับ (YES, yes, Y, y) ก็จะออกจากฟังก์ชั่นพร้อมทั้งคืนค่าด้วยรหัส "0" แต่ถ้าถ้ารับข้อมูลในลักษณะการตอบปฏิเสธ (NO, no, N, n) ก็จะออกจากฟังก์ชั่นพร้อมทั้งคืนค่าด้วยรหัส "1"

ในส่วนของตัวโปรแกรมหลักเมื่อมีการเรียกใช้ฟังก์ชั่นถามตอบนี้แล้ว จะสามารถตรวจสอบว่าผู้ใช้มีการตอบยืนยันหรือตอบปฏิเสธได้จากรหัสที่ถูกคืนค่ามาจากฟังก์ชั่นถามตอบนี้ โดยการตรวจสอบจากตัวแปรเชลล์ "$?" ในโปรแกรมหลักจะใช้ฟังก์ชั่นถามตอบสองครั้งดังต่อไปนี้

fyesno "\"$2\" does not exist, do you want to create it? [y/n] :"
และ
fyesno "There is some file in \"$2\", still process copy directory? [y/n] :"
สำหรับการประกาศฟังก์ชั่นจะต้องทำก่อนที่จะมีการเรียกใช้ฟังก์ชั่นนั้นๆ โดยที่จะต้องประกาศไว้แยกต่างหากจากส่วนของโปรแกรมหลักที่จะเรียกใช้ด้วย
#!/bin/sh

#--------------------------------------------------------

fyesno () {
    echo -n $1
    read ans
    while [ true ] ;do
        case "$ans" in
        y|Y|yes|YES) 
	    # 0 - on success (true in shell)
            return 0 ;;
        n|N|no|NO)
	    # 1 - on fail (false in shell)
	    return 1 ;;
	*)
	    echo -n "Expect \"yes\" or \"no\", please answer [y/n] :"
	    read ans
	esac
    done
}

#-----------------------------------------------------------

if [ $# -ne 2 ] ;then
    echo "Usage : $0 [source dir] [dest dir]"
    exit 1
fi

if [ ! -d $1 ] ;then
    echo "\"$1\" must be a directory, please check."
    exit 1
fi

if [ ! -w $2 ] ;then
    if [ ! -a $2 ] ;then
        fyesno "\"$2\" does not exist, do you want to create it? [y/n] :"
	if [ $? -eq 0 ] ;then
	    mkdir $2
	    if [ $? -ne 0 ] ;then
	        echo "Write \"$2\" error"
		exit 1
	    fi
        else 
	    echo "Ok, don't creat directory, so this will done nothing."
	    exit 0 
	fi
    else
        echo "\"$2\" does not have write permission, please check."
        exit 1
    fi
else
    if [ ! -d $2 ] ;then
        echo "\"$2\" is not a directory, please check."
        exit 1
    fi
fi

LISTFILE=`ls $2`
if [ ! -z "$LISTFILE" ] ;then
    fyesno "There is some file in \"$2\", still process copy directory? [y/n] :"
    if [ $? -eq 1 ] ;then
        echo "Ok, don't process, so this will done nothing."
        exit 0 
    fi
fi

SOURCEPARDIR=`dirname $1`
SOURCENAME=`basename $1`
DESTPARDIR=`dirname $2`
DESTNAME=`basename $2`
CURRDIR=`pwd`

echo "Copy in process..."
cd $1
if [ $DESTPARDIR = "." ] ;then
    # Destination is relative reference
    find -print | cpio -pd $CURRDIR/$DESTNAME
else
    # Destination is full reference
    find -print | cpio -pd $DESTPARDIR/$DESTNAME
fi
cd $CURRDIR
echo "Copy directory complete."
exit 0
ในส่วนของตัวโปรแกรมอาจมีบางส่วนที่ยังไม่สมบูรณ์ นอกจากเรื่องการปรับปรุงส่วนของฟังก์ชั่นถามตอบแล้วคุณอาจสามารถจะดัดแปลงแก้ไขเพื่อเพิ่มประสิทธิภาพของตัวโปรแกรมได้


HTML developed by Kaiwal Development Team (kaiwal@geocities.com)