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

问题描述:

我在写一个bash脚本。我需要当前工作目录始终是脚本所在的目录。如何将当前工作目录设置为脚本的目录?

默认行为是脚本中的当前工作目录是我从中运行它的shell的目录,但我不想要这种行为。

+0

您是否曾考虑将包装脚本放在/ usr/bin之类的某个位置,以便将光盘放入(硬编码)适当的目录中,然后执行脚本? – 2010-07-28 01:02:56

+2

为什么你需要脚本的目录?可能有更好的方法来解决潜在的问题。 – bstpierre 2010-07-28 03:59:02

+9

我只想指出,你称之为“显然不可取”的行为实际上是完全必要的 - 如果我运行'myscript path/to/file'我期望脚本评估相对于MY的路径/到/文件当前目录,而不是脚本恰好位于的目录。另外,BASH常见问题解答中提到的使用'ssh remotehost bash <. myscript class="text-secondary"> 2010-07-28 04:54:50

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

dirname返回'。'在Windows下使用bash时。所以,保罗的回答更好。 – Tvaroh 2013-05-28 10:10:35

+5

也返回'。'在Mac OSX – 2013-07-11 18:16:36

+2

值得注意的是,如果一个符号链接构成'$ 0'的一部分,事情就会中断。在你的脚本中你可能会想到,例如,'../../'指向脚本位置上方两个级别的目录,但是如果符号链接正在运行,则不一定是这种情况。 – 2013-12-24 08:51:30

这个脚本似乎为我工作:

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

pwd命令行相呼应的脚本作为当前工作目录的位置,无论身在何处,我从运行它。

+3

'realpath'不太可能安装在任何地方。根据OP的情况,这可能无关紧要。 – bstpierre 2010-07-28 03:42:18

+0

我的系统没有'realpath',但它确实有'readlink',它似乎是相似的。 – 2010-07-28 03:46:57

+0

这些命令在这方面看起来很危险 – Prospero 2013-06-25 03:30:46

获取真实路径到脚本

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

(这是答案同样在这里我的问题:Get the name of the directory where a script is executed

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

这很容易。有用。

+1

这应该是被接受的答案。适用于OSX和Linux Ubuntu。 – 2016-01-05 19:19:31

+3

当脚本B来自其他脚本A并且您需要使用相对于脚本B的路径时,此功能非常有用。谢谢。 – Enrico 2016-03-19 18:48:29

+1

这也适用于** Cygwin **对于我们这些不幸碰触Windows的人来说。 – 2016-12-18 18:33:22

下也可以工作:

cd "${0%/*}" 
+3

这应该是最简洁答案的复选标记。 – 2013-05-13 08:58:41

+1

当在Windows上使用bash时,使用$ {0%[\\ /] *} – Tvaroh 2013-05-28 10:09:16

+0

听起来很有趣,但它不能从当前目录中运行(改为传递脚本的名称)。 – kenorb 2013-07-19 10:31:23

如果你只需要打印当前工作目录,那么你可以遵循这一点。

$ vim test 

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

给执行权限:

chmod u+x test 

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

+0

问题是如何确保脚本在其_own_目录中运行,包括如果它不是工作目录。所以这不是一个答案。无论如何,为什么这样做,而不是...运行'pwd'?看起来像很多浪费的按键给我。 – 2016-10-23 19:01:28

尝试下面的简单的一衬垫:


对于所有UNIX/OSX/Linux的

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

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


对于Linux,Mac等* BSD:

cd $(dirname $(realpath $0)) 

以空格支持:

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

注:realpath应安装在最流行的Linux发行版默认情况下(如Ubuntu),但在一些它可能会丢失,所以你必须安装它。

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

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

对于Linux:

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

使用GNU * BSD/Mac上的readlink:

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

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


在bash

在bash你可以使用Parameter Expansions来实现,像:

cd ${0%/*} 

但如果脚本是从同一目录中运行它不工作。

或者,你可以在bash定义以下功能:

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

此功能需要1个参数。如果参数已经是绝对路径,则按原样打印它,否则打​​印$PWD变量+文件名参数(不带前缀./)。

或这里是Debian的.bashrc文件所采取的版本:

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

相关:

参见:

How can I get the behavior of GNU's readlink -f on a Mac?

+4

比流行的更好的答案,因为它解决了系统链接,并占了不同的操作系统。谢谢! – 2013-10-03 17:08:12

+0

感谢您的回答。在我的Mac上工作的第一个......但是,在“cp”命令中,@ switchorb是怎么做的? – TobyG 2014-06-12 07:18:10

+3

在命令中使用双短划线('--')来表示命令选项的结尾,因此包含破折号或其他特殊字符的文件不会破坏命令。尝试通过'touch'-test“'和'touch - -test'创建文件,然后通过'rm -test'和'rm - -test'删除文件,并查看其差异。 – kenorb 2014-06-12 08:15:32

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

你能解释你的答案吗? – Zulu 2015-10-27 12:31:46

+1

虽然这段代码可能有助于解决问题,但它并没有解释_why_和/或_how_它是如何回答问题的。提供这种附加背景将显着提高其长期教育价值。请[编辑]您的答案以添加解释,包括适用的限制和假设。 – 2016-10-24 16:16:40

echo $PWD 

PWD是一个环境变量。

+4

这只给出了从中调用的目录,而不是脚本所在的目录。 – dagelf 2017-08-09 08:00:18

echo $PWD | rev | cut -d'/' -f1 | rev