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


当前回答

基本版:

dir=$(dirname $0)

如果脚本可以通过$PATH调用,那么:

dir=$(dirname $(which $0))

如果脚本可能像这样调用:bash script.sh,那么:

dir=$(dirname $(which $0 2>/dev/null || realpath ./$0))

如果你感到极度不安全,那么:

dir="$(dirname -- "$(which -- "$0" 2>/dev/null || realpath -- "./$0")")"

其他回答

这应该能奏效:

echo `pwd`/`dirname $0`

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

这个问题的最佳答案是: 从内部获取Bash脚本的源目录

它是:

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

一行代码,它将提供脚本的完整目录名,无论从哪里调用脚本。

要了解它是如何工作的,你可以执行以下脚本:

#!/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'"

灵感来自blueyed的回答

read < <(readlink -f $0 | xargs dirname)
cd $REPLY

我发现的最有效的方法之一是

#!/bin/sh
relative_dir=`perl -e 'use Cwd "realpath";$pwd = realpath(shift); $pwd =~ s/\/[^\/]*$//; print $pwd' $0`
cd $relative_dir

使用符号链接工作,并为我的许多同事工作,无论他们选择的shell类型

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)"