基本上我需要运行与shell脚本文件位置相关的路径脚本,我如何将当前目录更改为脚本文件所在的相同目录?


当前回答

这一行代码告诉shell脚本在哪里,与您是否运行它或是否获取它无关。此外,它还会解析所涉及的任何符号链接,如果是这样的话:

dir=$(dirname $(test -L "$BASH_SOURCE" && readlink -f "$BASH_SOURCE" || echo "$BASH_SOURCE"))

顺便说一下,我认为您正在使用/bin/bash.

其他回答

在Bash中,你应该像这样得到你需要的东西:

#!/usr/bin/env bash

BASEDIR=$(dirname "$0")
echo "$BASEDIR"

正如marko所言:

BASEDIR=$(dirname $0)
echo $BASEDIR

除非你在脚本所在的目录中执行脚本,在这种情况下,你会得到一个值'。'

要解决这个问题,请使用:

current_dir=$(pwd)
script_dir=$(dirname $0)

if [ $script_dir = '.' ]
then
script_dir="$current_dir"
fi

现在可以在整个脚本中使用变量current_dir来引用脚本目录。然而,这可能仍然有符号链接的问题。

这应该能奏效:

echo `pwd`/`dirname $0`

它可能看起来很丑,这取决于它是如何被调用和cwd,但应该得到你需要去的地方(或者你可以调整字符串,如果你关心它的外观)。

如果你想获得实际的脚本目录(不管你是使用符号链接还是直接调用脚本),尝试:

BASEDIR=$(dirname $(realpath "$0"))
echo "$BASEDIR"

这在linux和macOS上都适用。我没看到有人提到realpath。不确定这种方法是否有任何缺点。

在macOS上,需要安装coreutils才能使用realpath。例如:brew install coreutils。

So many answers, all plausible, each with pro's and con's & slightly differeing objectives (which should probably be stated for each). Here's another solution that meets a primary objective of both being clear and working across all systems, on all bash (no assumptions about bash versions, or readlink or pwd options), and reasonably does what you'd expect to happen (eg, resolving symlinks is an interesting problem, but isn't usually what you actually want), handle edge cases like spaces in paths, etc., ignores any errors and uses a sane default if there are any issues.

每个组件都存储在一个单独的变量中,您可以单独使用:

# script path, filename, directory
PROG_PATH=${BASH_SOURCE[0]}      # this script's name
PROG_NAME=${PROG_PATH##*/}       # basename of script (strip path)
PROG_DIR="$(cd "$(dirname "${PROG_PATH:-$PWD}")" 2>/dev/null 1>&2 && pwd)"