https://my.oschina.net/leejun2005/blog/150662
http://blog.csdn.net/10km/article/details/51906821
如題,一般我們寫Shell腳本的時候,都傾向使用絕對路徑,這樣無論腳本在什么目錄執行,都應該起到相同的效果,但是有些時候,我們設計一個軟件包中的工具腳本,可能使用相對路徑更加靈活一點,因為你不知道用戶會在哪個目錄執行你的程序,就有了本文的題目。
常見的一種誤區,是使用 pwd 命令,該命令的作用是“print name of current/working directory”,這才是此命令的真實含義,當前的工作目錄,這里沒有任何意思說明,這個目錄就是腳本存放的目錄。所以,這是不對的。你可以試試 bash shell/a.sh,a.sh 內容是 pwd,你會發現,顯示的是執行命令的路徑 /home/june,並不是 a.sh 所在路徑:/home/june/shell/a.sh
另一個誤人子弟的答案,是 $0,這個也是不對的,這個$0是Bash環境下的特殊變量,其真實含義是:
Expands to the name of the shell or shell script. This is set at shell initialization. If bash is invoked with a file of commands, $0 is set to the name of that file. If bash is started with the -c option, then $0 is set to the first argument after the string to be executed, if one is present. Otherwise, it is set to the file name used to invoke bash, as given by argument zero.
這個$0有可能是好幾種值,跟調用的方式有關系:
-
使用一個文件調用bash,那$0的值,是那個文件的名字(沒說是絕對路徑噢)
-
使用-c選項啟動bash的話,真正執行的命令會從一個字符串中讀取,字符串后面如果還有別的參數的話,使用從$0開始的特殊變量引用(跟路徑無關了)
-
除此以外,$0會被設置成調用bash的那個文件的名字(沒說是絕對路徑)
下面對比下正確答案:
Jun@VAIO 192.168.1.216 23:52:54 ~ >
cat shell/a.sh
#!/bin/bash echo '$0: '$0 echo "pwd: "`pwd` echo "=============================" echo "scriptPath1: "$(cd `dirname $0`; pwd) echo "scriptPath2: "$(pwd) echo "scriptPath3: "$(dirname $(readlink -f $0)) echo "scriptPath4: "$(cd $(dirname ${BASH_SOURCE:-$0});pwd) echo -n "scriptPath5: " && dirname $(readlink -f ${BASH_SOURCE[0]}) Jun@VAIO 192.168.1.216 23:53:17 ~ > bash shell/a.sh $0: shell/a.sh pwd: /home/Jun ============================= scriptPath1: /home/Jun/shell scriptPath2: /home/Jun scriptPath3: /home/Jun/shell scriptPath4: /home/Jun/shell scriptPath5: /home/Jun/shell Jun@VAIO 192.168.1.216 23:54:54 ~ >
在此解釋下 scriptPath1 :
-
dirname $0,取得當前執行的腳本文件的父目錄
-
cd `dirname $0`,進入這個目錄(切換當前工作目錄)
-
pwd,顯示當前工作目錄(cd執行后的)
由此,我們獲得了當前正在執行的腳本的存放路徑。
-------------------------------------
有時候,我們需要知道當前執行的輸出shell腳本的所在絕對路徑,可以用dirname實現。
我們知道 dirname 可以獲取一個文件所在的路徑,dirname的用處是:
輸出已經去除了尾部的”/”字符部分的名稱;如果名稱中不包含”/”,
則顯示”.”(表示當前目錄)。
下面是dirname的命令行說明:
從上面的描述可知道,直接從dirname返回的未必是絕對路徑,取決於提供給dirname的參數是否是絕對路徑。
所以下面這樣的代碼中SHELL_FOLDER
中不一定是絕對路徑
SHELL_FOLDER=$(dirname "$0")
- 1
需要用cd和pwd命令配合獲取腳本所在絕對路徑,正確的寫法是這樣的,
SHELL_FOLDER=$(cd "$(dirname "$0")";pwd)
- 1
如果你覺得上面的寫法比較麻煩,還有一個方式獲取腳本的絕對路徑,就是借助readlink命令,下面是readlink的命令行說明:
所以用readlink命令我們可以直接獲取$0參數的全路徑文件名,然后再用dirname獲取其所在的絕對路徑:
SHELL_FOLDER=$(dirname $(readlink -f "$0"))
- 1
參考:
http://my.oschina.net/leejun2005/blog/150662
http://blog.csdn.net/zz198808/article/details/9319479