情景l(fā)inux--shell腳本中的路徑問(wèn)題

情景

使用shell編寫(xiě)腳本時(shí),經(jīng)常要使用到目錄和文件。而有時(shí)候,對(duì)于目錄和文件的使用總是達(dá)不到理想效果——目錄和文件總是不能在預(yù)想的位置創(chuàng)建,又或者,當(dāng)把腳本移動(dòng)到別的目錄執(zhí)行時(shí),卻不得不對(duì)修改腳本中文件或目錄的路徑,否則便不能使用,等等。

舉個(gè)簡(jiǎn)單的例子來(lái)說(shuō)明這種情景。
~/temp目錄下創(chuàng)建兩個(gè)目錄:test1test2

$ pwd
/home/j-tester/temp
$ ls -1
test1
test2

test1目錄下創(chuàng)建一個(gè)名稱(chēng)為getDate.sh的shell腳本,內(nèi)容如下:

$ pwd
/home/j-tester/temp/test1
$ cat getDate.sh 
date +%Y%m%d-%H%M%S > shijian.txt

腳本的需求是:
執(zhí)行date +%Y%m%d-%H%M%S命令,并將命令的結(jié)果保存到該腳本所在的目錄下的shijian.txt文件中。

為其賦予執(zhí)行權(quán)限,然后運(yùn)行它:

$ chmod +x getDate.sh
$ ./getDate.sh

查看當(dāng)前目錄,確實(shí)產(chǎn)生了一個(gè)名為shijian.txt的文件,內(nèi)容是執(zhí)行腳本時(shí)的時(shí)間20170421-121406

$ ls -1
getDate.sh
shijian.txt
$ cat shijian.txt
20170421-121406

如果我們切換目錄到../test2/,然后執(zhí)行getDate.sh會(huì)發(fā)生什么呢?

$ cd ../test2/
$ pwd
/home/j-tester/temp/test2

切換了目錄,執(zhí)行時(shí)可以用絕對(duì)路徑執(zhí)行,也可以用相對(duì)路徑來(lái)執(zhí)行,這里使用了相對(duì)路徑:

$ ../test1/getDate.sh

腳本執(zhí)行后,查看../test1/目錄下的shijian.txt文件,內(nèi)容還是之前的時(shí)間20170421-121406,這說(shuō)明腳本的執(zhí)行并未對(duì)test1目錄下的shijian.txt文件產(chǎn)生效果:

$ ls -1 ../test1/
getDate.sh
shijian.txt
$ cat ../test1/shijian.txt 
20170421-121406

而查看此時(shí)的當(dāng)前目錄(/home/j-tester/temp/test2),卻有一個(gè)shijian.txt文件,內(nèi)容中的時(shí)間比之前的時(shí)間要新20170421-121833,而這正是進(jìn)入到test2目錄之后執(zhí)行腳本時(shí)的時(shí)間:

$ ls -1
shijian.txt
$ cat shijian.txt 
20170421-121833

由上,可以預(yù)見(jiàn)的是,在不同的目錄下執(zhí)行getDate.sh文件,都會(huì)在這些目錄下產(chǎn)生shijian.txt文件。這與預(yù)期的在getDate.sh腳本所在的目錄下產(chǎn)生shijian.txt文件的需求是不符的。

其實(shí),不僅僅是上面這個(gè)腳本,許多腳本都有這樣的現(xiàn)象:只有在進(jìn)入了腳本所在的目錄下執(zhí)行腳本,才會(huì)產(chǎn)生預(yù)期的效果。在windows系列系統(tǒng)中也有軟件有這樣的情況:一個(gè)可執(zhí)行文件,使用絕對(duì)路徑或相對(duì)路徑執(zhí)行它時(shí)會(huì)沒(méi)有效果或者干脆直接報(bào)錯(cuò),而只有先進(jìn)入到這個(gè)可執(zhí)行文件所在的目錄后,再執(zhí)行它才可以正常使用。

這是因?yàn)?,正常情況下,這類(lèi)腳本預(yù)期的執(zhí)行目錄是它所在的目錄,而當(dāng)你在其它目錄執(zhí)行它時(shí)就會(huì)出現(xiàn)這樣那樣的問(wèn)題。

本文主要討論這類(lèi)問(wèn)題該如何解決。

方案

方案一

可以為用到的目錄或文件設(shè)置絕對(duì)路徑。

在上例中,可以用絕對(duì)路徑表示shijian.txt,就可以實(shí)現(xiàn)無(wú)論在任何目錄執(zhí)行getDate.sh,其輸出都是~/temp/test1/shijian.txt。

$ cat ~/temp/test1/getDate.sh 
date +%Y%m%d-%H%M%S > ~/temp/test1/shijian.txt

這樣做的弊端是:
getDate.sh移動(dòng)到別的目錄執(zhí)行時(shí),產(chǎn)生的文件shijian.txt還是原來(lái)的目錄,而非新目錄。所以,當(dāng)移動(dòng)腳本后,還需要修改腳本中的絕對(duì)路徑。

方案二

既然腳本中使用的目錄或文件期望基于腳本的所在目錄,那么可以在腳本中先進(jìn)入到這個(gè)目錄里,后續(xù)要使用目錄和文件時(shí),都基于此目錄,用相對(duì)路徑描述。

具體做法:

我們知道,shell中有幾個(gè)特殊的變量,其中$0表示shell腳本本身的文件名。
命令dirname是去掉后接參數(shù)的非目錄的后綴,所以dirname $0就是腳本所在的目錄:

$ pwd
/home/j-tester/temp

修改腳本的內(nèi)容如下:

$ cat ./test1/getDate.sh 
echo "shell name is:$0"
echo "shell dir is :`dirname $0`"
date +%Y%m%d-%H%M%S > shijian.txt

使用相對(duì)路徑執(zhí)行腳本:

$ ./test1/getDate.sh 
shell name is:./test1/getDate.sh
shell dir is :./test1

使用絕對(duì)路徑執(zhí)行腳本:

$ ~/temp/test1/getDate.sh 
shell name is:/home/j-tester/temp/test1/getDate.sh
shell dir is :/home/j-tester/temp/test1

在腳本所在目錄,用相對(duì)路徑執(zhí)行腳本:

$ cd test1
$ ./getDate.sh 
shell name is:./getDate.sh
shell dir is :.

通過(guò)上述結(jié)果可知,我們可以使用命令替換的方式,先cd進(jìn)入到腳本所在的目錄,然后使用pwd命令返回目錄的絕對(duì)路徑,將這個(gè)路徑保持到變量里,以便后續(xù)調(diào)用。

更進(jìn)一步,可以將獲取腳本所在目錄優(yōu)化為一句話(huà)代碼

path="$(cd "$(dirname $0)";pwd)"

如果要進(jìn)入這個(gè)目錄,只需執(zhí)行:

cd ${path}

如果你還希望在腳本中使用你執(zhí)行腳本時(shí)所在的目錄,可以在這之前,把pwd命令的結(jié)果保存到一個(gè)變量里:

run_path=`pwd`

使用相對(duì)路徑的好處在于:
無(wú)需因?yàn)槟_本的絕對(duì)路徑發(fā)生了變化而不得不修改腳本中的相關(guān)路徑。

當(dāng)然,有時(shí)候使用絕對(duì)路徑是在所難免的,但只要你進(jìn)行了這方面的處理,腳本就會(huì)變得更通用,維護(hù)成本低很多。

擴(kuò)展知識(shí)

  • 相對(duì)路徑和絕對(duì)路徑
  • 特殊變量,如$0
  • 命令替換$()
  • 雙引號(hào)""和反引號(hào)``的使用
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容