我如何找到一个Bash脚本位于该脚本内部的目录的路径?

我想用Bash脚本作为另一个应用程序的启动器,我想将工作目录更改为Bash脚本所在的目录,所以我可以在该目录中的文件上运行,如下:

$ ./application

当前回答

我不认为这是像其他人这样容易的。 pwd 不工作,因为当前的目录不一定是与脚本的目录。 $0 不总是有信息。

./script

/usr/bin/script

script

在第一和第三方式 $0 没有完整的路径信息. 在第二和第三, pwd 不工作. 唯一的方式来获得目录的第三方式将是通过路径运行并找到文件与正确的匹配。

做你正在要求的一种方式,就是在 /usr/share 目录中的数据硬编码,并将其引用到其完整的路径。

其他回答

没有百分之百可携带和可靠的方式来要求一个路径到当前的脚本目录,特别是在不同背景,如Cygwin,MinGW,MSYS,Linux等之间,这个问题没有正确和完全解决在Bash的年龄。

在源命令的情况下,我建议用这样的东西取代源命令:

function include()
{
  if [[ -n "$CURRENT_SCRIPT_DIR" ]]; then
    local dir_path=... get directory from `CURRENT_SCRIPT_DIR/$1`, depends if $1 is absolute path or relative ...
    local include_file_path=...
  else
    local dir_path=... request the directory from the "$1" argument using one of answered here methods...
    local include_file_path=...
  fi
  ... push $CURRENT_SCRIPT_DIR in to stack ...
  export CURRENT_SCRIPT_DIR=... export current script directory using $dir_path ...
  source "$include_file_path"
  ... pop $CURRENT_SCRIPT_DIR from stack ...
}

从现在开始,使用包括(...)是基于以前的CURRENT_SCRIPT_DIR在你的脚本。

我自己最接近这一点的实施: https://sourceforge.net/p/tacklelib/tacklelib/HEAD/tree/trunk/bash/tacklelib/bash_tacklelib https://github.com/andry81/tacklelib/tree/trunk/bash/tacklelib/bash_tacklelib

(搜索 tkl_include 函数)

命名命令是最基本的,简单地将路径到0美元(脚本名称)变量的名称:

dirname -- "$0";

但是,正如Matt b指出的那样,返回的路径取决于脚本的名称。 pwd 不做工作,因为它只告诉你当前的目录是什么,而不是脚本的目录是什么。

有些人提到了阅读链接命令,但最简单的是,你可以使用:

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

阅读链接将解决脚本路径从文件系统的根源到绝对路径,因此,任何包含单点或双点的路径,图标和/或象征性链接将解决到完整路径。

#!/usr/bin/env 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:

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

$_ 值得提到为 $0 的替代品。 如果您正在运行来自 Bash 的脚本,可将接受的答案缩短到:

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

请注意,这应该是您的脚本中的第一个声明。

这在Bash 3.2中工作:

path="$( dirname "$( which "$0" )" )"

如果您在 $PATH 中有 ~/bin 目录,则在此目录中有 A. 它源于 ~/bin/lib/B. 您知道所包含的目录与原始目录相对,在 lib 子目录中,但不是与用户当前目录相对。

以以下方式解决问题(A内部):

source "$( dirname "$( which "$0" )" )/lib/B"

无论用户在哪里,还是他/她如何呼叫脚本,这总是会工作。

好吧,如果在路上,字母和字母只是不会切断它,走路是艰难的(如果父母没有出口PATH?!)。

然而,盾牌必须对其脚本有一个开放的手稿,而在Bash手稿是#255。

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

为我工作。