情景
使用shell編寫腳本時妓笙,經(jīng)常要使用到目錄和文件。而有時候,對于目錄和文件的使用總是達不到理想效果——目錄和文件總是不能在預想的位置創(chuàng)建旷赖,又或者,當把腳本移動到別的目錄執(zhí)行時更卒,卻不得不對修改腳本中文件或目錄的路徑等孵,否則便不能使用,等等蹂空。
舉個簡單的例子來說明這種情景俯萌。
在~/temp
目錄下創(chuàng)建兩個目錄:test1
和test2
:
$ pwd
/home/j-tester/temp
$ ls -1
test1
test2
在test1
目錄下創(chuà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
命令上枕,并將命令的結果保存到該腳本所在的目錄下的shijian.txt
文件中咐熙。
為其賦予執(zhí)行權限,然后運行它:
$ chmod +x getDate.sh
$ ./getDate.sh
查看當前目錄辨萍,確實產(chǎn)生了一個名為shijian.txt
的文件棋恼,內(nèi)容是執(zhí)行腳本時的時間20170421-121406
:
$ ls -1
getDate.sh
shijian.txt
$ cat shijian.txt
20170421-121406
如果我們切換目錄到../test2/
,然后執(zhí)行getDate.sh
會發(fā)生什么呢锈玉?
$ cd ../test2/
$ pwd
/home/j-tester/temp/test2
切換了目錄爪飘,執(zhí)行時可以用絕對路徑執(zhí)行,也可以用相對路徑來執(zhí)行嘲玫,這里使用了相對路徑:
$ ../test1/getDate.sh
腳本執(zhí)行后悦施,查看../test1/
目錄下的shijian.txt
文件,內(nèi)容還是之前的時間20170421-121406
去团,這說明腳本的執(zhí)行并未對test1
目錄下的shijian.txt
文件產(chǎn)生效果:
$ ls -1 ../test1/
getDate.sh
shijian.txt
$ cat ../test1/shijian.txt
20170421-121406
而查看此時的當前目錄(/home/j-tester/temp/test2
)抡诞,卻有一個shijian.txt
文件,內(nèi)容中的時間比之前的時間要新20170421-121833
土陪,而這正是進入到test2
目錄之后執(zhí)行腳本時的時間:
$ ls -1
shijian.txt
$ cat shijian.txt
20170421-121833
由上昼汗,可以預見的是,在不同的目錄下執(zhí)行getDate.sh
文件鬼雀,都會在這些目錄下產(chǎn)生shijian.txt
文件顷窒。這與預期的在getDate.sh
腳本所在的目錄下產(chǎn)生shijian.txt
文件的需求是不符的。
其實源哩,不僅僅是上面這個腳本鞋吉,許多腳本都有這樣的現(xiàn)象:只有在進入了腳本所在的目錄下執(zhí)行腳本,才會產(chǎn)生預期的效果励烦。在windows系列系統(tǒng)中也有軟件有這樣的情況:一個可執(zhí)行文件谓着,使用絕對路徑或相對路徑執(zhí)行它時會沒有效果或者干脆直接報錯,而只有先進入到這個可執(zhí)行文件所在的目錄后坛掠,再執(zhí)行它才可以正常使用赊锚。
這是因為治筒,正常情況下,這類腳本預期的執(zhí)行目錄是它所在的目錄舷蒲,而當你在其它目錄執(zhí)行它時就會出現(xiàn)這樣那樣的問題耸袜。
本文主要討論這類問題該如何解決。
方案
方案一
可以為用到的目錄或文件設置絕對路徑牲平。
在上例中堤框,可以用絕對路徑表示shijian.txt
,就可以實現(xiàn)無論在任何目錄執(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
移動到別的目錄執(zhí)行時,產(chǎn)生的文件shijian.txt
還是原來的目錄藐窄,而非新目錄资昧。所以,當移動腳本后荆忍,還需要修改腳本中的絕對路徑格带。
方案二
既然腳本中使用的目錄或文件期望基于腳本的所在目錄,那么可以在腳本中先進入到這個目錄里刹枉,后續(xù)要使用目錄和文件時叽唱,都基于此目錄,用相對路徑描述微宝。
具體做法:
我們知道棺亭,shell中有幾個特殊的變量,其中$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
使用相對路徑執(zhí)行腳本:
$ ./test1/getDate.sh
shell name is:./test1/getDate.sh
shell dir is :./test1
使用絕對路徑執(zhí)行腳本:
$ ~/temp/test1/getDate.sh
shell name is:/home/j-tester/temp/test1/getDate.sh
shell dir is :/home/j-tester/temp/test1
在腳本所在目錄,用相對路徑執(zhí)行腳本:
$ cd test1
$ ./getDate.sh
shell name is:./getDate.sh
shell dir is :.
通過上述結果可知岳守,我們可以使用命令替換的方式凄敢,先cd
進入到腳本所在的目錄,然后使用pwd
命令返回目錄的絕對路徑湿痢,將這個路徑保持到變量里涝缝,以便后續(xù)調(diào)用。
更進一步譬重,可以將獲取腳本所在目錄優(yōu)化為一句話代碼:
path="$(cd "$(dirname $0)";pwd)"
如果要進入這個目錄拒逮,只需執(zhí)行:
cd ${path}
如果你還希望在腳本中使用你執(zhí)行腳本時所在的目錄,可以在這之前臀规,把pwd
命令的結果保存到一個變量里:
run_path=`pwd`
使用相對路徑的好處在于:
無需因為腳本的絕對路徑發(fā)生了變化而不得不修改腳本中的相關路徑消恍。
當然,有時候使用絕對路徑是在所難免的以现,但只要你進行了這方面的處理狠怨,腳本就會變得更通用,維護成本低很多邑遏。
擴展知識
- 相對路徑和絕對路徑
- 特殊變量佣赖,如$0
- 命令替換$()
- 雙引號
""
和反引號``的使用