如何将当前工作目录设置为Bash中脚本的目录?

530779 次浏览

#!/bin/bash
mypath=`realpath $0`
cd `dirname $mypath`
pwd

#!/bin/bash
cd "$(dirname "$0")"

if [ -L $0 ] ; then
ME=$(readlink $0)
else
ME=$0
fi
DIR=$(dirname $ME)

cd "$(dirname "${BASH_SOURCE[0]}")"

cd "${0%/*}"

$ vim test


#!/bin/bash
pwd
:wq to save the test file.

chmod u+x test


dir=$(cd -P -- "$(dirname -- "$0")" && pwd -P)

dir=$(cd -P -- "$(dirname -- "${BASH_SOURCE[0]}")" && pwd -P)


对于Linux,Mac和其他*BSD:

cd "$(dirname "$(realpath "$0")")";

注意:默认情况下,realpath应该安装在最流行的Linux发行版(如Ubuntu)中,但在某些发行版中可能会丢失,因此您必须安装它。

注意:如果您使用的是Bash,请使用${BASH_SOURCE[0]}而不是$0,否则路径在获取时可能会中断(source/.)。

否则,您可以尝试类似的东西(它将使用第一个现有工具):

cd "$(dirname "$(readlink -f "$0" || realpath "$0")")"

具体Linux:

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

在*BSD/Mac上使用GNU readlink:

cd "$(dirname "$(greadlink -f "$0")")"

注意:您需要安装coreutils (例如1.安装自制,2.brew install coreutils)。


在bash

在bash中,您可以使用参数扩展来实现这一点,例如:

cd "${0%/*}"

但如果脚本从同一目录运行,则不起作用。

或者,您可以在bash中定义以下函数:

realpath () {
[[ $1 = /* ]] && echo "$1" || echo "$PWD/${1#./}"
}

此函数接受1个参数。如果参数已经有绝对路径,请按原样打印,否则打印$PWD变量+文件名参数(没有./前缀)。

或者这是来自Debian.bashrc文件的版本:

function realpath()
{
f=$@
if [ -d "$f" ]; then
base=""
dir="$f"
else
base="/$(basename "$f")"
dir=$(dirname "$f")
fi
dir=$(cd "$dir" && /bin/pwd)
echo "$dir$base"
}

相关:

另见:

如何在Mac上获取GNU的readlink-f的行为?

cd "`dirname $(readlink -f ${0})`"
echo $PWD

PWD是一个环境变量。

接受的答案适用于其他地方没有符号链接的脚本,例如$PATH

#!/bin/bash
cd "$(dirname "$0")"

但是,如果脚本通过符号链接运行,

ln -sv ~/project/script.sh ~/bin/;
~/bin/script.sh

这将cd到~/bin/目录而不是~/project/目录,如果cd的目的是包含相对于~/project/的依赖项,这可能会破坏您的脚本

符号链接安全答案如下:

#!/bin/bash
cd "$(dirname "$(readlink -f "${BASH_SOURCE[0]}")")"  # cd current directory

readlink -f需要解析潜在符号链接文件的绝对路径。

需要引号来支持可能包含空格的文件路径(不好的做法,但假设情况并非如此并不安全)

我拿了这个,它起作用了。

#!/bin/bash
cd "$(dirname "$0")"
CUR_DIR=$(pwd)

大多数答案要么不处理通过相对路径符号链接的文件,要么不是单行程序,要么不处理BSD(Mac)。完成所有这三个的解决方案是:

HERE=$(cd "$(dirname "$BASH_SOURCE")"; cd -P "$(dirname "$(readlink "$BASH_SOURCE" || echo .)")"; pwd)

首先,cd到bash对脚本目录的概念。然后重新链接文件以查看它是否是符号链接(相对或其他),如果是,cd到该目录。如果不是,cd到当前目录(保持单行代码所必需的)。然后通过pwd回显当前目录。

您可以将--添加到cd和readlink的参数中,以避免类似选项的目录问题,但我不会为大多数目的而烦恼。

你可以在这里看到完整的解释和插图:

https://www.binaryphile.com/bash/2020/01/12/determining-the-location-of-your-script-in-bash.html

这里有很多正确的答案,但对我来说更有用的一个(确保脚本的相对路径保持可预测/有效)是使用pushd/popd:

pushd "$(dirname ${BASH_SOURCE:0})"
trap popd EXIT


# ./xyz, etc...

这会将源文件的目录推送到导航堆栈上,从而更改工作目录,但随后,当脚本退出时(无论出于何种原因,包括失败),trap将运行popd,恢复当前工作目录在它执行之前。如果脚本转到cd然后失败,你的终端可能会在执行结束后处于不可预测的状态——陷阱可以防止这种情况。