关于bash:如何将当前工作目录设置为脚本的目录?

How to set current working directory to the directory of the script?

我正在写一个bash脚本。我需要当前的工作目录始终是脚本所在的目录。

默认行为是,脚本中的当前工作目录是运行它的shell的目录,但我不希望出现这种行为。


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


以下内容也有效:

1
cd"${0%/*}"

语法在这个stackoverflow答案中进行了详细描述。


尝试以下简单的一句话:

适用于所有UNIX/OSX/Linux

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

注意:命令中使用双破折号(--)表示命令选项的结束,因此包含破折号或其他特殊字符的文件不会破坏命令。

对于Linux、Mac和其他*BSD:

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

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

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

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

对于特定于Linux的:

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

在*bsd/mac上使用gnu readlink:

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

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

在狂欢中

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

1
cd"${0%/*}"

但如果脚本是从同一个目录运行,它就不起作用。

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

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

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

或者这里是从debian .bashrc文件中获取的版本:

1
2
3
4
5
6
7
8
9
10
11
12
13
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"
}

相关:

  • 如何检测运行shell脚本的当前目录?

  • 从脚本本身中获取bash脚本的源目录

  • 带有OS X的bash脚本绝对路径

  • bash脚本获取完整路径的可靠方法

参见:

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


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

这很容易。它起作用了。


对于在其他地方没有符号链接的脚本(如$PATH中),接受的答案很好。

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

但是,如果脚本是通过symlink运行的,

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

这将进入~/bin/目录,而不是~/project/目录,如果cd的目的是包括与~/project/相关的依赖项,则可能会破坏脚本。

symlink安全答案如下:

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

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

需要引号来支持可能包含空白的文件路径(不好的做法,但假设不是这样做是不安全的)


这个脚本似乎对我有用:

1
2
3
4
#!/bin/bash
mypath=`realpath $0`
cd `dirname $mypath`
pwd

pwd命令行将脚本的位置作为当前工作目录进行回声,无论从何处运行它。


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


获取脚本的真正路径

1
2
3
4
5
6
if [ -L $0 ] ; then
    ME=$(readlink $0)
else
    ME=$0
fi
DIR=$(dirname $ME)

(这是我这里相同问题的答案:获取执行脚本的目录的名称)


1
echo $PWD

pwd是一个环境变量。


如果您只需要打印当前的工作目录,那么您可以按此操作。

1
2
3
4
5
$ vim test

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

授予执行权限:

1
chmod u+x test

然后通过./test执行脚本,就可以看到当前的工作目录。