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

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

$ ./application

当前回答

我尝试了所有这些,没有一个工作,一个非常接近,但有一个小错误打破了它;他们忘了把路放在引用标志上。

而且,很多人假设你正在从一个阴影中运行脚本,所以当你打开一个新的脚本时,他们会忘记它到你的家。

请尝试这个目录为尺寸:

/var/No one/Thought/About Spaces Being/In a Directory/Name/And Here's your file.text

这是正确的,无论你如何或在哪里运行它:

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

因此,要使它实际上有用,这里是如何改变运行脚本的目录:

cd "`dirname "$0"`"

其他回答

以下是一個符合 POSIX 的單線:

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

# test
echo $SCRIPT_PATH

下面将返回剧本的当前目录

工作,如果它是源,或者不源工作,如果运行在当前的目录,或某些其他目录.工作,如果相对目录被使用.工作与 bash,不确定其他<unk>。

/tmp/a/b/c $ . ./test.sh
/tmp/a/b/c

/tmp/a/b/c $ . /tmp/a/b/c/test.sh
/tmp/a/b/c

/tmp/a/b/c $ ./test.sh
/tmp/a/b/c

/tmp/a/b/c $ /tmp/a/b/c/test.sh
/tmp/a/b/c

/tmp/a/b/c $ cd

~ $ . /tmp/a/b/c/test.sh
/tmp/a/b/c

~ $ . ../../tmp/a/b/c/test.sh
/tmp/a/b/c

~ $ /tmp/a/b/c/test.sh
/tmp/a/b/c

~ $ ../../tmp/a/b/c/test.sh
/tmp/a/b/c

测试.sh

#!/usr/bin/env bash

# snagged from: https://stackoverflow.com/a/51264222/26510
function toAbsPath {
    local target
    target="$1"

    if [ "$target" == "." ]; then
        echo "$(pwd)"
    elif [ "$target" == ".." ]; then
        echo "$(dirname "$(pwd)")"
    else
        echo "$(cd "$(dirname "$1")"; pwd)/$(basename "$1")"
    fi
}

function getScriptDir(){
  local SOURCED
  local RESULT
  (return 0 2>/dev/null) && SOURCED=1 || SOURCED=0

  if [ "$SOURCED" == "1" ]
  then
    RESULT=$(dirname "$1")
  else
    RESULT="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd )"
  fi
  toAbsPath "$RESULT"
}

SCRIPT_DIR=$(getScriptDir "$0")
echo "$SCRIPT_DIR"

没有百分之百可携带和可靠的方式来要求一个路径到当前的脚本目录,特别是在不同背景,如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)与 realpath 和/或 dirname 相结合,它适用于 Bash 和 Shell。

#!/usr/bin/env bash

RELATIVE_PATH="${0}"
RELATIVE_DIR_PATH="$(dirname "${0}")"
FULL_DIR_PATH="$(realpath "${0}" | xargs dirname)"
FULL_PATH="$(realpath "${0}")"

echo "RELATIVE_PATH->${RELATIVE_PATH}<-"
echo "RELATIVE_DIR_PATH->${RELATIVE_DIR_PATH}<-"
echo "FULL_DIR_PATH->${FULL_DIR_PATH}<-"
echo "FULL_PATH->${FULL_PATH}<-"

结果将是这样的:

# RELATIVE_PATH->./bin/startup.sh<-
# RELATIVE_DIR_PATH->./bin<-
# FULL_DIR_PATH->/opt/my_app/bin<-
# FULL_PATH->/opt/my_app/bin/startup.sh<-

$0 是脚本本身的名称

4.4 特殊变量类型

例如:LozanoMatheus/get_script_paths.sh

我认为最简单的答案是原始变量的参数扩展:

#!/usr/bin/env bash

DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd )"
echo "opt1; original answer: $DIR"
echo ''

echo "opt2; simple answer  : ${BASH_SOURCE[0]%/*}"

它应该产生产量如:

$ /var/tmp/test.sh
opt1; original answer: /var/tmp

opt2; simple answer  : /var/tmp

变量/参数扩展 ${BASH_SOURCE[0]%/*}”似乎更容易保持。