方便的條件語句
如果您曾用 C 編寫過與文件相關(guān)的代碼,則應(yīng)該知道:要比較特定文件是否比另一個文件新需要大量工作。那是因為 C 沒有任何內(nèi)置語法來進行這種比較,必須使用兩個 stat() 調(diào)用和兩個 stat 結(jié)構(gòu)來進行手工比較。相反,bash 內(nèi)置了標(biāo)準(zhǔn)文件比較運算符,因此,確定“/tmp/myfile 是否可讀”與查看“$myvar 是否大于 4”一樣容易。
for x in ../* mystuff/*
do
echo $x is a silly file
done
在上例中,bash 相對于當(dāng)前工作目錄執(zhí)行通配符擴展,就象在命令行中使用相對路徑一樣。研究一下通配符擴展。您將注意到,如果在通配符中使用絕對路徑,bash 將通配符擴展成一個絕對路徑列表。否則,bash 將在后面的字列表中使用相對路徑。如果只引用當(dāng)前工作目錄中的文件(例如,如果輸入 "for x in *"),則產(chǎn)生的文件列表將沒有路徑信息的前綴。請記住,可以使用 "basename" 可執(zhí)行程序來除去前面的路徑信息,如下所示:
for x in /var/log/*
do
echo `basename $x` is a file living in /var/log
done
tarview() {
echo -n "Displaying contents of $1 "
if [ ${1##*.} = tar ]
then
echo "(uncompressed tar)"
tar tvf $1
elif [ ${1##*.} = gz ]
then
echo "(gzip-compressed tar)"
tar tzvf $1
elif [ ${1##*.} = bz2 ]
then
echo "(bzip2-compressed tar)"
cat $1 | bzip2 -d | tar tvf -
fi
}
另一種情況
可以使用 "case" 語句來編寫上面的代碼。您知道如何編寫嗎?
我們在上面定義了一個名為 "tarview" 的函數(shù),它接收一個自變量,即某種類型的 tar 文件。在執(zhí)行該函數(shù)時,它確定自變量是哪種 tar 文件類型(未壓縮的、gzip 壓縮的或 bzip2 壓縮的),打印一行信息性消息,然后顯示 tar 文件的內(nèi)容。應(yīng)該如下調(diào)用上面的函數(shù)(在輸入、粘貼或找到該函數(shù)后,從腳本或命令行調(diào)用它):
名稱空間
經(jīng)常需要在函數(shù)中創(chuàng)建環(huán)境變量。雖然有可能,但是還有一個技術(shù)細節(jié)應(yīng)該了解。在大多數(shù)編譯語言(如 C)中,當(dāng)在函數(shù)內(nèi)部創(chuàng)建變量時,變量被放置在單獨的局部名稱空間中。因此,如果在 C 中定義一個名為 myfunction 的函數(shù),并在該函數(shù)中定義一個名為 "x" 的自變量,則任何名為 "x" 的全局變量(函數(shù)之外的變量)將不受它的印象,從而消除了負作用。
在 C 中是這樣,但在 bash 中卻不是。在 bash 中,每當(dāng)在函數(shù)內(nèi)部創(chuàng)建環(huán)境變量,就將其添加到 全局名稱空間。這意味著,該變量將重寫函數(shù)之外的全局變量,并在函數(shù)退出之后繼續(xù)存在:
#!/usr/bin/env bash
myvar="hello"
myfunc() {
myvar="one two three"
for x in $myvar
do
echo $x
done
}
myfunc
echo $myvar $x
運行此腳本時,它將輸出 "one two three three",這顯示了在函數(shù)中定義的 "$myvar" 如何影響全局變量 "$myvar",以及循環(huán)控制變量 "$x" 如何在函數(shù)退出之后繼續(xù)存在(如果 "$x" 全局變量存在,也將受到影響)。
if [ -d work ]
then
# remove old work directory if it exists
rm -rf work
fi
mkdir work
cd work
tar xzf /usr/src/distfiles/sed-3.02.tar.gz
cd sed-3.02
./configure --prefix=/usr
make
if [ $# -ne 2 ]
then
echo "lease specify two args - .ebuild file and unpack, compile or all"
exit 1
fi
if [ -z "$DISTDIR" ]
then
# set DISTDIR to /usr/src/distfiles if not already set
DISTDIR=/usr/src/distfiles
fi
export DISTDIR
ebuild_unpack() {
#make sure we're in the right directory
cd ${ORIGDIR}
if [ -d ${WORKDIR} ]
then
rm -rf ${WORKDIR}
fi
mkdir ${WORKDIR}
cd ${WORKDIR}
if [ ! -e ${DISTDIR}/${A} ]
then
echo "${DISTDIR}/${A} does not exist. Please download first."
exit 1
fi
tar xzf ${DISTDIR}/${A}
echo "Unpacked ${DISTDIR}/${A}."
#source is now correctly unpacked
}
ebuild_compile() {
#make sure we're in the right directory
cd ${SRCDIR}
if [ ! -d "${SRCDIR}" ]
then
echo "${SRCDIR} does not exist -- please unpack first."
exit 1
fi
./configure --prefix=/usr
make
}
if [ -e "$1" ]
then
source $1
else
echo "Ebuild file $1 not found."
exit 1
fi
export SRCDIR=${WORKDIR}/${P}
case "${2}" in
unpack)
ebuild_unpack
;;
compile)
ebuild_compile
;;
all)
ebuild_unpack
ebuild_compile
;;
*)
echo "lease specify unpack, compile or all as the second arg"
exit 1
;;
esac
user_compile() {
#we're already in ${SRCDIR}
if [ -e configure ]
then
#run configure script if it exists
./configure --prefix=/usr
fi
#run make
make
}
ebuild_compile() {
if [ ! -d "${SRCDIR}" ]
then
echo "${SRCDIR} does not exist -- please unpack first."
exit 1
fi
#make sure we're in the right directory
cd ${SRCDIR}
user_compile
}
這行代碼指示 make 同時編譯四個程序。 MAKE="make -j4" 自變量告訴 make,向其啟動的任何子 make 進程傳遞 -j4 選項。
這里是 ebuild 程序的最終版本:
ebuild,最終版本
#!/usr/bin/env bash
if [ $# -ne 2 ]
then
echo "lease specify ebuild file and unpack, compile or all"
exit 1
fi
source /etc/ebuild.conf
if [ -z "$DISTDIR" ]
then
# set DISTDIR to /usr/src/distfiles if not already set
DISTDIR=/usr/src/distfiles
fi
export DISTDIR
ebuild_unpack() {
#make sure we're in the right directory
cd ${ORIGDIR}
if [ -d ${WORKDIR} ]
then
rm -rf ${WORKDIR}
fi
mkdir ${WORKDIR}
cd ${WORKDIR}
if [ ! -e ${DISTDIR}/${A} ]
then
echo "${DISTDIR}/${A} does not exist. Please download first."
exit 1
fi
tar xzf ${DISTDIR}/${A}
echo "Unpacked ${DISTDIR}/${A}."
#source is now correctly unpacked
}
user_compile() {
#we're already in ${SRCDIR}
if [ -e configure ]
then
#run configure script if it exists
./configure --prefix=/usr
fi
#run make
make $MAKEOPTS MAKE="make $MAKEOPTS"
}
ebuild_compile() {
if [ ! -d "${SRCDIR}" ]
then
echo "${SRCDIR} does not exist -- please unpack first."
exit 1
fi
#make sure we're in the right directory
cd ${SRCDIR}
user_compile
}
if [ -e "$1" ]
then
source $1
else
echo "Ebuild file $1 not found."
exit 1
fi
export SRCDIR=${WORKDIR}/${P}
case "${2}" in
unpack)
ebuild_unpack
;;
compile)
ebuild_compile
;;
all)
ebuild_unpack
ebuild_compile
;;
*)
echo "lease specify unpack, compile or all as the second arg"
exit 1
;;
esac