如何在MacOS上获取shell脚本的绝对路径名?

Iva*_*hov 30 macos bash shell sh

readlink -f在MacOS上不存在.我设法在网上找到的唯一可用的Mac OS解决方案是这样的:

if [[ $(echo $0 | awk '/^\//') == $0 ]]; then
    ABSPATH=$(dirname $0)
else
    ABSPATH=$PWD/$(dirname $0)
fi
Run Code Online (Sandbox Code Playgroud)

任何人都可以向这个看似微不足道的任务提出更优雅的建议吗?

Gor*_*son 64

另一个(也相当丑陋)的选择:

ABSPATH=$(cd "$(dirname "$0")"; pwd)
Run Code Online (Sandbox Code Playgroud)

  • +1,但也许ABSPATH = $(cd $(dirname $ 0); pwd)/ $(basename $ 0) (4认同)
  • 警告附带的好解决方案:(a)对于符号链接的脚本,返回_symlink's_目录(这可能不是问题); (b)如果脚本是_sourced_,则`$ 0`不反映脚本路径; 解决这个问题,使用(Bash特定的)`$ BASH_SOURCE`代替; (c)使用以`-`开头的(异常)路径,命令将中断(通过使用`--`作为`cd`和`dirname`命令的第一个参数)可以轻松修复; 最后,最好不要使用全大写的shell变量名,以避免与环境变量和特殊的shell变量发生冲突. (3认同)

Gre*_*Fox 9

获取shell脚本的绝对路径

从我的.bashrc中挖出一些旧脚本,并稍微更新了语法,添加了一个测试套件.

支持

  • source ./script(由.点运算符调用时)
  • 绝对路径/路径/到/脚本
  • 像./script这样的相对路径
  • /path/dir1/../dir2/dir3/../script
  • 从符号链接调用时
  • 当符号链接嵌套时,例如) foo->dir1/dir2/bar bar->./../doe doe->script
  • 调用者更改脚本名称时

它已在成功的实际项目中进行了测试和使用,但可能存在我不知道的极端情况.
如果您能够找到这种情况,请告诉我.
(首先,我知道这不会在sh shell上运行)

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`]"
Run Code Online (Sandbox Code Playgroud)

已知的问题

脚本必须位于某个磁盘上,让它通过网络. 如果您尝试从PIPE运行此脚本,它将无法正常工作

wget -o /dev/null -O - http://host.domain/dir/script.sh |bash
Run Code Online (Sandbox Code Playgroud)

从技术上讲,它是未定义的.
实际上,没有理智的方法来检测这一点.

使用的测试用例

以及检查它是否有效的当前测试用例.

#!/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
Run Code Online (Sandbox Code Playgroud)

PurpleFox又名GreenFox