Unix shell脚本找出脚本文件所在的目录?

基本上我需要运行与脚本文件位置相关的path的脚本,我怎么能改变当前目录到脚本文件所在的目录?

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

#!/usr/bin/env bash BASEDIR=$(dirname "$0") echo "$BASEDIR" 

原来的文章包含解决scheme(忽略回应,他们没有添加任何有用的东西)。 有趣的工作是由提到的unix命令readlink和选项-f 。 当脚本被绝对以及相对path调用时起作用。

对于bash,sh,ksh:

 #!/bin/bash # Absolute path to this script, eg /home/user/bin/foo.sh SCRIPT=$(readlink -f "$0") # Absolute path this script is in, thus /home/user/bin SCRIPTPATH=$(dirname "$SCRIPT") echo $SCRIPTPATH 

对于tcsh,csh:

 #!/bin/tcsh # Absolute path to this script, eg /home/user/bin/foo.csh set SCRIPT=`readlink -f "$0"` # Absolute path this script is in, thus /home/user/bin set SCRIPTPATH=`dirname "$SCRIPT"` echo $SCRIPTPATH 

另请参阅: https : //stackoverflow.com/a/246128/59087

假设你正在使用bash

 #!/bin/bash current_dir=$(pwd) script_dir=$(dirname $0) echo $current_dir echo $script_dir 

这个脚本在运行时应该打印你所在的目录,然后打印脚本所在的目录,例如,当从/(脚本在/ home / mez /中)调用它时,它输出

 / /home/mez 

请记住,从命令的输出中分配variables时,将命令封装在$(和)中 – 否则您将无法获得所需的输出。 `

如果你使用bash ….

 #!/bin/bash pushd $(dirname "${0}") > /dev/null basedir=$(pwd -L) # Use "pwd -P" for the path without links. man bash for more info. popd > /dev/null echo "${basedir}" 

早些时候对一个答案的评论说,但在所有其他答案中很容易错过。

当使用bash时:

 echo this file: $BASH_SOURCE echo this dir: `dirname $BASH_SOURCE` 

Bash参考手册,5.2 Bashvariables

正如马克所说:

 BASEDIR=$(dirname $0) echo $BASEDIR 

除非您从脚本所在的同一个目录执行脚本,否则您将获得“。”值。

为了解决这个问题,请使用:

 current_dir=$(pwd) script_dir=$(dirname $0) if [ $script_dir = '.' ] then script_dir="$current_dir" fi 

您现在可以在整个脚本中使用variablescurrent_dir来引用脚本目录。 但是,这可能仍然存在符号链接问题。

 cd $(dirname $(readlink -f $0)) 

受到blueyed的回答启发

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

这个问题的最佳答案在这里得到了回答:
从内部获取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'" 

让我们来做POSIX:

 a="/$0"; a=${a%/*}; a=${a:-.}; a=${a#/}/; BASEDIR=$(cd $a; pwd) 

testing了许多兼容Bourne的shell,包括BSD。

据我所知,我是作者,我把它列入公有领域。 欲了解更多信息,请参阅: https : //www.jasan.tk/posix/2017/05/11/posix_shell_dirname_replacement

这么多的答案,都是有道理的,每个都有专业人士和学生的不同目标(这些应该可以分别说明)。 这是另一个解决scheme,它符合所有系统中清除和工作的主要目标(对bash版本,或者readlinkpwd选项没有任何假设),并且合理地执行你期望发生的事情(例如,parsing符号链接是一个有趣的问题,但通常不是你真正想要的),处理边缘情况,如path中的空格等,忽略任何错误,如果有任何问题,使用默认的默认值。

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

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

这应该够了吧:

 echo `pwd`/`dirname $0` 

它可能看起来很丑,取决于它是如何被调用的,而且应该让你去你需要的地方(或者你可以调整string,如果你关心的话)。