找到绝对目录

找到绝对目录

这是场景:

foo/
> data/
> stuff/
> scripts/ -> /.../generic/scripts

当从任何位置(其他文件夹或文件夹内)调用时foo/scripts/bar.sh,我希望能够使用脚本foo/datafoo/stuff

但是,如果我只是使用,foo_dir='dirname $0'/..那么它将进入符号链接指向的目录! (并获取generic而不是foo!)

如果我使用某种模式来吃掉 的末尾$0,那么它也不起作用,因为您也可以从目录内部调用脚本。

所以,最后,我唯一发现的就是这个极其丑陋的东西:

dir=`dirname $0`
cd $dir
dir=`pwd | sed -r 's_/[^/]+$__'`
cd -

...但我确信有更好的方法,不是吗?

我用的是:

dir=$( dirname $( cd `dirname $0`; pwd ) )

我不知道它是否完美,但它的表现似乎符合预期。

答案1

您可以使用以下单行:

DIR="$(cd "$( dirname "$0" )" && pwd )"

答案2

抱歉第一次没有更仔细地阅读你的问题。

代替:

foo_dir = $(dirname $0)/..

怎么样:

foo_dir = $(dirname $(dirname $0))

然而,这只适用于 $0 中至少有一个目录组件的情况。你有这个保证吗?

答案3

是的,..符号链接的存在是一个真正的问题。罗布·派克写道关于这个问题的整篇论文

我建议您避免..使用dirname绝对路径名,因此:

case $0 in
  /*) where="$0" ;;
  *)  where="$(pwd)/$0" ;;
esac
# postcondition: $where is an absolute pathname for script
# N.B $where = .../foo/scripts/command

base="$(dirname "$(dirname "$where")")"
# postcondition: $base = .../foo

resource="$base/data"

我实际上使用第一个习惯用法(从可能的相对路径名恢复绝对路径名),我的~/bin目录中有一个专门用于此目的的脚本。

一旦你处理绝对路径名,dirname就会表现得明智。

答案4

你的帖子有点漫无目的,有些陈述似乎是矛盾的,但如果我的理解是正确的,你有一个$0形式foo/scripts/bar.sh,并且你正在尝试提取该foo部分。您还可以保证该路径中始终至少有两级目录(如果您只有bar.sh,那就完蛋了)。然后你可以去掉路径的最后两个组成部分:

DIR=${0%/*/*}

不过,您可以通过 调用脚本scripts/bar.sh,在这种情况下,简单的模式替换将不起作用。更不用说通过$PATH.您可以将其设置为有条件:

case $0 in
  */*/*) DIR=${0%/*/*};;
  ?*/*) DIR=.;;
  /*) echo 1>&2 "Storing $0 in the root directory is not supported, aborting."
      exit 125;;
  *) # The script was called through the `PATH`
    IFS=:; set -f; unset DIR
    for d in $PATH; do
      if [ -x "$d/$0" ]; then
        # If you put relative directories in your PATH, you get what you deserve.
        DIR=${d%/*};;
      fi
    done
    if [ -z "$DIR" ]; then
      echo 1>&2 "$0: Fatal error: I can't find myself."
      exit 125
    fi
    unset IFS; set +f;;
esac

相关内容