bash get script path




从内部获取Bash脚本的源目录 (20)

dirname命令是最基本的,只需解析直到$ 0(脚本名称)变量的文件名的路径:

dirname "$0"

但是,正如matt b指出的那样,返回的路径根据脚本的调用方式而有所不同。 pwd不能完成这项工作,因为它只告诉你当前目录是什么,而不是脚本所在的目录。另外,如果执行了一个脚本的符号链接,你将获得一个(可能是相对的)路径到链接所在的位置,而不是实际的脚本。

其他一些人提到了readlink命令,但最简单的是,您可以使用:

dirname "$(readlink -f "$0")"

readlink将脚本路径解析为文件系统根目录的绝对路径。 因此,任何包含单点或双点,波浪线和/或符号链接的路径都将被解析为完整路径。

这是一个演示这些内容的脚本, whatdir.sh:

#!/bin/bash
echo "pwd: `pwd`"
echo "\$0: $0"
echo "basename: `basename $0`"
echo "dirname: `dirname $0`"
echo "dirname/readlink: $(dirname $(readlink -f $0))"

使用相对路径在我的主目录中运行此脚本:

>>>$ ./whatdir.sh 
pwd: /Users/phatblat
$0: ./whatdir.sh
basename: whatdir.sh
dirname: .
dirname/readlink: /Users/phatblat

同样,但使用脚本的完整路径:

>>>$ /Users/phatblat/whatdir.sh 
pwd: /Users/phatblat
$0: /Users/phatblat/whatdir.sh
basename: whatdir.sh
dirname: /Users/phatblat
dirname/readlink: /Users/phatblat

现在更改目录:

>>>$ cd /tmp
>>>$ ~/whatdir.sh 
pwd: /tmp
$0: /Users/phatblat/whatdir.sh
basename: whatdir.sh
dirname: /Users/phatblat
dirname/readlink: /Users/phatblat

最后使用符号链接来执行脚本:

>>>$ ln -s ~/whatdir.sh whatdirlink.sh
>>>$ ./whatdirlink.sh 
pwd: /tmp
$0: ./whatdirlink.sh
basename: whatdirlink.sh
dirname: .
dirname/readlink: /Users/phatblat

如何在该脚本中获取Bash脚本所在目录的路径?

例如,假设我想使用Bash脚本作为另一个应用程序的启动器。 我想将工作目录更改为Bash脚本所在的目录,因此我可以对该目录中的文件进行操作,如下所示:

$ ./application

$_值得一提,作为0美元的替代品。 如果您从bash运行脚本,则接受的答案可以缩短为:

DIR="$( dirname "$_" )"

请注意,这必须是脚本中的第一个语句。


使用dirname "$0"

#!/bin/bash
echo "The script you are running has basename `basename "$0"`, dirname `dirname "$0"`"
echo "The present working directory is `pwd`"

如果您没有从包含它的目录运行脚本,则单独使用pwd将不起作用。

[[email protected] ~]$ pwd
/home/matt
[[email protected] ~]$ ./test2.sh
The script you are running has basename test2.sh, dirname .
The present working directory is /home/matt
[[email protected] ~]$ cd /tmp
[[email protected] tmp]$ ~/test2.sh
The script you are running has basename test2.sh, dirname /home/matt
The present working directory is /tmp

对e-satisf和3bcdnlklvc04a解决方案的略微修改在他们的回答中指出

SCRIPT_DIR=''
pushd "$(dirname "$(readlink -f "$BASH_SOURCE")")" > /dev/null && {
    SCRIPT_DIR="$PWD"
    popd > /dev/null
}    

这应该仍然适用于他们列出的所有情况。

编辑:由于konsolebox,在推送失败后防止弹出


尝试以下交叉兼容的解决方案:

CWD="$(cd -P -- "$(dirname -- "$0")" && pwd -P)"

as realpathreadlink命令并不总是可用(取决于操作系统),并且${BASH_SOURCE[0]}仅在bash shell中可用。

或者,您可以在bash中尝试以下功能:

realpath () {
  [[ $1 = /* ]] && echo "$1" || echo "$PWD/${1#./}"
}

此函数需要1个参数。如果参数已经是绝对路径,则按原样打印,否则打印$PWD变量+文件名参数(不带./前缀)。

有关:


尝试使用:

real=$(realpath $(dirname $0))

我会用这样的东西:

# retrieve the full pathname of the called script
scriptPath=$(which $0)

# check whether the path is a link or not
if [ -L $scriptPath ]; then

    # it is a link then retrieve the target path and get the directory name
    sourceDir=$(dirname $(readlink -f $scriptPath))

else

    # otherwise just get the directory name of the script path
    sourceDir=$(dirname $scriptPath)

fi

我尝试了其中的每一个,但没有一个有效。 一个非常接近,但有一个小虫子,打破了它; 他们忘了用引号包裹路径。

还有很多人认为你是从shell运行脚本所以忘记当你打开一个新的脚本它默认你的家。

试试这个目录的大小:

/ var /没有人/思想/关于空间存在/在目录/名称/这里是你的file.text

无论您运行的方式和位置如何,这都是正确的。

#!/bin/bash
echo "pwd: `pwd`"
echo "\$0: $0"
echo "basename: `basename "$0"`"
echo "dirname: `dirname "$0"`"

因此,为了使它真正有用,这里是如何更改到正在运行的脚本的目录:

cd "`dirname "$0"`"

希望有所帮助


我认为最好的紧凑型解决方案是:

"$( cd "$( echo "${BASH_SOURCE[0]%/*}" )"; pwd )"

除了Bash之外,没有任何依赖。使用dirnamereadlinkbasename最终会导致兼容性问题,因此如果可能的话,最好避免使用它们。


我认为这并不像其他人那样容易实现。 pwd不起作用,因为当前目录不一定是脚本的目录。 $ 0并不总是有信息。 考虑以下三种调用脚本的方法。

./script

/usr/bin/script

script

在第一种和第三种方式中,$ 0没有完整的路径信息。 在第二和第三,pwd不起作用。 以第三种方式获取目录的唯一方法是遍历路径并找到具有正确匹配的文件。 基本上代码必须重做操作系统的功能。

执行所要求的一种方法是仅对/ usr / share目录中的数据进行硬编码,并通过完整路径引用它。 无论如何数据都不在/ usr / bin目录中,所以这可能是要做的事情。


简短回答:

`dirname $0`

或( preferably ):

$(dirname "$0")

这些都不适用于Finder在OS X中启动的bash脚本 - 我最终使用:

SCRIPT_LOC="`ps -p $$ | sed /PID/d | sed s:.*/Network/:/Network/: |
sed s:.*/Volumes/:/Volumes/:`"

不漂亮,但它完成了工作。


这应该这样做:

DIR=$(dirname "$(readlink -f "$0")")

与路径中的符号链接和空格一起使用。 有关dirnamereadlink的信息,请参见手册页。

编辑:

从评论轨道看来它似乎不适用于Mac OS。 我不知道为什么会这样。 有什么建议?


这是一个简单,正确的方法:

actual_path=$(readlink -f "${BASH_SOURCE[0]}")
script_dir=$(dirname "$actual_path")

说明:

  • ${BASH_SOURCE[0]} - 脚本的完整路径。 即使在脚本被提取时,这个值也是正确的,例如source <(echo 'echo $0') ${BASH_SOURCE[0]} source <(echo 'echo $0')打印bash ,而用${BASH_SOURCE[0]}替换它将打印脚本的完整路径。 (当然,这假设您可以依赖Bash。)

  • readlink -f - 以递归方式解析指定路径中的所有符号链接。 这是GNU扩展,在(例如)BSD系统上不可用。 如果你正在运行Mac,你可以使用Homebrew来安装GNU coreutils并用greadlink -f取代它。

  • 当然dirname获取路径的父目录。


这是特定于Linux的,但您可以使用:

SELF=$(readlink /proc/$$/fd/255)

这是符合POSIX标准的单线程:

SCRIPT_PATH=`dirname "$0"`; SCRIPT_PATH=`eval "cd \"$SCRIPT_PATH\" && pwd"`

# test
echo $SCRIPT_PATH

嗯,如果在路径basename&dirname中只是不打算切断它并且走路很难(如果父节点没有导出PATH怎么办!)。但是,shell必须有一个打开它的脚本句柄,而在bash中句柄是#255。

SELF=`readlink /proc/$$/fd/255`

适合我。


#!/bin/sh
PRG="$0"

# need this for relative symlinks
while [ -h "$PRG" ] ; do
   PRG=`readlink "$PRG"`
done

scriptdir=`dirname "$PRG"`

DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null && pwd )"

是一个有用的单行程序,它将为您提供脚本的完整目录名称,无论它在何处被调用。

只要用于查找脚本的路径的最后一个组件不是符号链接(目录链接正常),它就会起作用。 如果您还想解决脚本本身的任何链接,您需要一个多线解决方案:

SOURCE="${BASH_SOURCE[0]}"
while [ -h "$SOURCE" ]; do # resolve $SOURCE until the file is no longer a symlink
  DIR="$( cd -P "$( dirname "$SOURCE" )" >/dev/null && pwd )"
  SOURCE="$(readlink "$SOURCE")"
  [[ $SOURCE != /* ]] && SOURCE="$DIR/$SOURCE" # if $SOURCE was a relative symlink, we need to resolve it relative to the path where the symlink file was located
done
DIR="$( cd -P "$( dirname "$SOURCE" )" >/dev/null && pwd )"

最后一个将适用于别名, sourcebash -c ,符号链接等的任意组合。

注意:如果在运行此代码段之前cd到其他目录,结果可能不正确! 另外,请注意$CDPATH陷阱

要了解它是如何工作的,请尝试运行这个更详细的表单:

#!/bin/bash

SOURCE="${BASH_SOURCE[0]}"
while [ -h "$SOURCE" ]; do # resolve $SOURCE until the file is no longer a symlink
  TARGET="$(readlink "$SOURCE")"
  if [[ $TARGET == /* ]]; then
    echo "SOURCE '$SOURCE' is an absolute symlink to '$TARGET'"
    SOURCE="$TARGET"
  else
    DIR="$( dirname "$SOURCE" )"
    echo "SOURCE '$SOURCE' is a relative symlink to '$TARGET' (relative to '$DIR')"
    SOURCE="$DIR/$TARGET" # if $SOURCE was a relative symlink, we need to resolve it relative to the path where the symlink file was located
  fi
done
echo "SOURCE is '$SOURCE'"
RDIR="$( dirname "$SOURCE" )"
DIR="$( cd -P "$( dirname "$SOURCE" )" && pwd )"
if [ "$DIR" != "$RDIR" ]; then
  echo "DIR '$RDIR' resolves to '$DIR'"
fi
echo "DIR is '$DIR'"

它将打印如下:

SOURCE './scriptdir.sh' is a relative symlink to 'sym2/scriptdir.sh' (relative to '.')
SOURCE is './sym2/scriptdir.sh'
DIR './sym2' resolves to '/home/ubuntu/dotfiles/fo fo/real/real1/real2'
DIR is '/home/ubuntu/dotfiles/fo fo/real/real1/real2'

SCRIPT_DIR=$( cd ${0%/*} && pwd -P )




directory