How to get absolute path name of shell script on MacOS?
MacOS上不存在
1 2 3 4 5 | if [[ $(echo $0 | awk '/^\//') == $0 ]]; then ABSPATH=$(dirname $0) else ABSPATH=$PWD/$(dirname $0) fi |
对于这个看似微不足道的任务,有人能提出更优雅的建议吗?
另一个(所以不是丑女)选项:
1 | ABSPATH=$(cd"$(dirname"$0")"; pwd) |
shell脚本的绝对路径(get
挖出来。那些从我的一些旧的脚本语法A位,和更新,增加了一个测试套件。
支持
- 源代码/脚本(时称为"由
. 点操作符) - 绝对路径路径/到/脚本
- 相对路径/脚本类。
- dir1 /路径/ / / / / / dir2 dir3脚本。
- 当被从链接
- 当链接是嵌套
foo->dir1/dir2/bar bar->./../doe doe->script EC) - 当呼叫者的名字更改脚本
它已经进行了测试,使用真实的项目和成功案例,然而,有可能是我不知道的角落。如果你能找到这样一个情况,请让我知道。(一),我知道这是不运行在SH壳)
代码
1 2 3 4 5 6 7 8 9 10 11 | pushd . > /dev/null SCRIPT_PATH="${BASH_SOURCE[0]}"; while([ -h"${SCRIPT_PATH}" ]) do cd"`dirname"${SCRIPT_PATH}"`" SCRIPT_PATH="$(readlink"`basename"${SCRIPT_PATH}"`")"; done cd"`dirname"${SCRIPT_PATH}"`"> /dev/null SCRIPT_PATH="`pwd`"; popd > /dev/null echo"srcipt=[${SCRIPT_PATH}]" echo"pwd =[`pwd`]" |
已知的问题
脚本必须在磁盘的某个地方,让它过的网络。如果你尝试运行脚本从一管它不工作
1 | wget -o /dev/null -O - http://host.domain/dir/script.sh |bash |
从技术上讲,它是不明确的。我们几乎没有理智的方式,来检测本。
使用测试用例
这是检查测试用例流和它的作品。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 | #!/bin/bash # setup test enviroment mkdir -p dir1/dir2 mkdir -p dir3/dir4 ln -s ./dir1/dir2/foo bar ln -s ./../../dir3/dir4/test.sh dir1/dir2/foo ln -s ./dir1/dir2/foo2 bar2 ln -s ./../../dir3/dir4/doe dir1/dir2/foo2 cp test.sh ./dir1/dir2/ cp test.sh ./dir3/dir4/ cp test.sh ./dir3/dir4/doe P="`pwd`" echo"--- 01" echo"base =[${P}]" && ./test.sh echo"--- 02" echo"base =[${P}]" && `pwd`/test.sh echo"--- 03" echo"base =[${P}]" && ./dir1/dir2/../../test.sh echo"--- 04" echo"base =[${P}/dir3/dir4]" && ./bar echo"--- 05" echo"base =[${P}/dir3/dir4]" && ./bar2 echo"--- 06" echo"base =[${P}/dir3/dir4]" && `pwd`/bar echo"--- 07" echo"base =[${P}/dir3/dir4]" && `pwd`/bar2 echo"--- 08" echo"base =[${P}/dir1/dir2]" && `pwd`/dir3/dir4/../../dir1/dir2/test.sh echo"--- 09" echo"base =[${P}/dir1/dir2]" && ./dir1/dir2/test.sh echo"--- 10" echo"base =[${P}/dir3/dir4]" && ./dir3/dir4/doe echo"--- 11" echo"base =[${P}/dir3/dir4]" && ./dir3/dir4/test.sh echo"--- 12" echo"base =[${P}/dir3/dir4]" && `pwd`/dir3/dir4/doe echo"--- 13" echo"base =[${P}/dir3/dir4]" && `pwd`/dir3/dir4/test.sh echo"--- 14" echo"base =[${P}/dir3/dir4]" && `pwd`/dir1/dir2/../../dir3/dir4/doe echo"--- 15" echo"base =[${P}/dir3/dir4]" && `pwd`/dir1/dir2/../../dir3/dir4/test.sh echo"--- 16" echo"base s=[${P}]" && source test.sh echo"--- 17" echo"base s=[${P}]" && source `pwd`/test.sh echo"--- 18" echo"base s=[${P}/dir1/dir2]" && source ./dir1/dir2/test.sh echo"--- 19" echo"base s=[${P}/dir3/dir4]" && source ./dir1/dir2/../../dir3/dir4/test.sh echo"--- 20" echo"base s=[${P}/dir3/dir4]" && source `pwd`/dir1/dir2/../../dir3/dir4/test.sh echo"--- 21" pushd . >/dev/null cd .. echo"base x=[${P}/dir3/dir4]" ./`basename"${P}"`/bar popd >/dev/null |
purplefox又名greenfox
本方法使用bash I suggest。你的第一个光盘的目录,然后你把当前目录使用PWD。返回后,你必须确保你的旧目录的脚本创建一个侧不影响其他脚本调用它。
1 2 3 4 | cd"$(dirname --"$0")" dir="$PWD" echo"$dir" cd - > /dev/null |
这个解决方案是安全的和复杂的路径。你将永远不会有麻烦与空间的特殊性或如果你把引号。
注:/dev/null是需要"CD"或打印它的返回路径。
所以注意
1 2 | $ realpath bin /Users/nhed/bin |
我发现这很有用的符号链接与动态链接的作品/ GNU readlink(只因为我个F标志):
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | # detect if GNU readlink is available on OS X if ["$(uname)" ="Darwin" ]; then which greadlink > /dev/null || { printf 'GNU readlink not found ' exit 1 } alias readlink="greadlink" fi # create a $dirname variable that contains the file dir dirname=$(dirname"$(readlink -f"$0")") # use $dirname to find a relative file cat"$dirname"/foo/bar.txt |
你可以尝试在你的脚本是这样的吗?
1 | echo $(pwd)/"$0" |
在我的机器它的显示:
1 | /home/barun/codes/ns2/link_down/./test.sh |
这是绝对路径名的shell脚本。
如果你不使用Perl:心灵
1 | ABSPATH=$(perl -MCwd=realpath -e"print realpath '$0'") |
我使用下面的函数来emulate"情况下,F’的脚本有两个运行在Linux和Mac OS X。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 | #!/bin/bash # This was re-worked on 2018-10-26 after der@build correctly # observed that the previous version did not work. # Works on both linux and Mac OS X. # The"pwd -P" re-interprets all symlinks. function read-link() { local path=$1 if [ -d $path ] ; then local abspath=$(cd $path; pwd -P) else local prefix=$(cd $(dirname -- $path) ; pwd -P) local suffix=$(basename $path) local abspath="$prefix/$suffix" fi if [ -e $abspath ] ; then echo $abspath else echo 'error: does not exist' fi } # Example usage. while (( $# )) ; do printf '%-24s - '"$1" read-link $1 shift done |
这是一些普通的Mac OS X的输出目标。
1 2 3 4 5 | $ ./example.sh /usr/bin/which /bin/which /etc/racoon ~/Downloads /usr/bin/which - /usr/bin/which /bin/which - error: does not exist /etc/racoon - /private/etc/racoon /Users/jlinoff/Downloads - /Users/jlinoff/Downloads |
Linux是一个目标输出。
1 2 3 4 5 | $ ./example.sh /usr/bin/which /bin/whichx /etc/init.d ~/Downloads /usr/bin/which - /usr/bin/which /bin/whichx - error: does not exist /etc/init.d - /etc/init.d /home/jlinoff/Downloads - /home/jlinoff/Downloads |
如果你使用的是
本作品,只要它不是一个链接,和一marginally:也不丑
1 | ABSPATH=$(dirname $(pwd -P $0)/${0#\.\/}) |
这是我在这里使用,可能需要调整或有a
1 2 3 4 5 6 7 8 9 10 11 12 | abspath () { case"${1}" in [./]*) local ABSPATH="$(cd ${1%/*}; pwd)/${1##*/}" echo"${ABSPATH/\/\///}" ;; *) echo"${PWD}/${1}" ;; esac } |
这是在所有的文件和你可以诅咒它
第一个案例交易相对路径的路径由CD - ING和PWD图让它
在第二个案例是一个本地文件处理(在# # } { 1美元/人没有工作)
这对于符号链接不会松开。