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


当前回答

假设您正在使用bash

#!/bin/bash

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

echo $current_dir
echo $script_dir

这个脚本应该打印您所在的目录,然后是脚本所在的目录。例如,当使用/home/mez/中的脚本从/调用它时,它输出

/
/home/mez

请记住,当从命令的输出为变量赋值时,请将命令包装在$(and)中—否则将得不到所需的输出。

其他回答

这个问题的最佳答案是: 从内部获取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'"

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

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

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

对于tcsh,您可以使用:h变量修饰符来检索路径。

需要注意的是,如果脚本作为tcsh myscript执行。Csh,那么您将只获得脚本名称。一个解决方法是验证路径,如下所示。

#!/bin/tcsh

set SCRIPT_PATH = $0:h
if ( $SCRIPT_PATH == $0 ) then
        set SCRIPT_PATH = "."
endif

$SCRIPT_PATH/compile.csh > $SCRIPT_PATH/results.txt

关于变量修饰语的更多信息可以在https://learnxinyminutes.com/docs/tcsh/上找到

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)"
BASE_DIR="$(cd "$(dirname "$0")"; pwd)";
echo "BASE_DIR => $BASE_DIR"