简体   繁体   English

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

[英]How can I set the current working directory to the directory of the script in Bash?

I'm writing a Bash script.我正在写一个 Bash 脚本。 I need the current working directory to always be the directory that the script is located in.我需要当前工作目录始终是脚本所在的目录。

The default behavior is that the current working directory in the script is that of the shell from which I run it, but I do not want this behavior.默认行为是脚本中的当前工作目录是我运行它的 shell 的目录,但我不希望这种行为。

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

The following also works:以下也有效:

cd "${0%/*}"

The syntax is thoroughly described in this StackOverflow answer. StackOverflow 答案中详细描述了语法。

Try the following simple one-liners:尝试以下简单的单线:


For all UNIX/OSX/Linux适用于所有 UNIX/OSX/Linux

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

Bash重击

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

Note: A double dash (--) is used in commands to signify the end of command options, so files containing dashes or other special characters won't break the command.注意:命令中使用双破折号 (--) 表示命令选项的结束,因此包含破折号或其他特殊字符的文件不会破坏命令。

Note: In Bash, use ${BASH_SOURCE[0]} in favor of $0 , otherwise the path can break when sourcing it ( source / . ).注意:在 Bash 中,使用${BASH_SOURCE[0]} $0 ,否则路径在获取它时可能会中断( source / . )。


For Linux, Mac and other *BSD:对于 Linux、Mac 和其他 *BSD:

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

Note: realpath should be installed in the most popular Linux distribution by default (like Ubuntu), but in some it can be missing, so you have to install it.注意:默认情况下, realpath应该安装在最流行的 Linux 发行版中(如 Ubuntu),但在某些发行版中可能会丢失,因此您必须安装它。

Note: If you're using Bash, use ${BASH_SOURCE[0]} in favor of $0 , otherwise the path can break when sourcing it ( source / . ).注意:如果您使用 Bash,请使用${BASH_SOURCE[0]} $0 ,否则在获取路径时可能会中断( source / . )。

Otherwise you could try something like that (it will use the first existing tool):否则,您可以尝试类似的操作(它将使用第一个现有工具):

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

For Linux specific:对于 Linux 特定:

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

Using GNU readlink on *BSD/Mac:在 *BSD/Mac 上使用 GNU readlink:

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

Note: You need to have coreutils installed (eg 1. Install Homebrew , 2. brew install coreutils ).注意:您需要安装coreutils (例如 1. 安装Homebrew , 2. brew install coreutils )。


In bash在 bash 中

In bash you can use Parameter Expansions to achieve that, like:在 bash 中,您可以使用参数扩展来实现,例如:

cd "${0%/*}"

but it doesn't work if the script is run from the same directory.但如果脚本从同一目录运行,则它不起作用。

Alternatively you can define the following function in bash:或者,您可以在 bash 中定义以下函数:

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

This function takes 1 argument.此函数接受 1 个参数。 If argument has already absolute path, print it as it is, otherwise print $PWD variable + filename argument (without ./ prefix).如果参数已经有绝对路径,则按原样打印,否则打印$PWD变量 + 文件名参数(不带./前缀)。

or here is the version taken from Debian .bashrc file:或者这里是从 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"
}

Related:有关的:

See also:也可以看看:

How can I get the behavior of GNU's readlink -f on a Mac? 如何在 Mac 上获得 GNU 的 readlink -f 的行为?

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

It's easy.这很简单。 It works.有用。

The accepted answer works well for scripts that have not been symlinked elsewhere, such as into $PATH .接受的答案适用于尚未在其他地方进行符号链接的脚本,例如$PATH

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

However if the script is run via a symlink,但是,如果脚本通过符号链接运行,

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

This will cd into the ~/bin/ directory and not the ~/project/ directory, which will probably break your script if the purpose of the cd is to include dependencies relative to ~/project/这将 cd 进入~/bin/目录而不是~/project/目录,如果cd的目的是包含相对于~/project/依赖项,这可能会破坏您的脚本

The symlink safe answer is below:符号链接安全答案如下:

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

readlink -f is required to resolve the absolute path of the potentially symlinked file.需要readlink -f来解析潜在符号链接文件的绝对路径。

The quotes are required to support filepaths that could potentially contain whitespace (bad practice, but its not safe to assume this won't be the case)需要引号来支持可能包含空格的文件路径(不好的做法,但假设情况并非如此是不安全的)

This script seems to work for me:这个脚本似乎对我有用:

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

The pwd command line echoes the location of the script as the current working directory no matter where I run it from.无论我从哪里运行脚本,pwd 命令行都会将脚本的位置作为当前工作目录进行回显。

Get the real path to your script获取脚本的真实路径

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

(This is answer to the same my question here: Get the name of the directory where a script is executed ) (这是对我的相同问题的回答: 获取执行脚本的目录的名称

I take this and it works.我把这个,它的工作原理。

#!/bin/bash
cd "$(dirname "$0")"
CUR_DIR=$(pwd)
cd "`dirname $(readlink -f ${0})`"

Most answers either don't handle files which are symlinked via a relative path, aren't one-liners or don't handle BSD (Mac).大多数答案要么不处理通过相对路径符号链接的文件,要么不是单行文件,要么不处理 BSD (Mac)。 A solution which does all three is:一个解决所有三个问题的解决方案是:

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

First, cd to bash's conception of the script's directory.首先, cd 到 bash 脚本目录的概念。 Then readlink the file to see if it is a symlink (relative or otherwise), and if so, cd to that directory.然后读取链接文件以查看它是否是符号链接(相对或其他),如果是,则 cd 到该目录。 If not, cd to the current directory (necessary to keep things a one-liner).如果没有, cd 到当前目录(必须保持单行)。 Then echo the current directory via pwd .然后通过pwd回显当前目录。

You could add -- to the arguments of cd and readlink to avoid issues of directories named like options, but I don't bother for most purposes.您可以在 cd 和 readlink 的参数中添加--以避免出现类似选项的目录问题,但我不会为大多数目的而烦恼。

You can see the full explanation with illustrations here:您可以在此处查看带插图的完整说明:

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

There are a lot of correct answers in here, but one that tends to be more useful for me (making sure a script's relative paths remain predictable/work) is to use pushd/popd:这里有很多正确的答案,但对我来说更有用的答案(确保脚本的相对路径保持可预测/有效)是使用 pushd/popd:

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

# ./xyz, etc...

This will push the source file's directory on to a navigation stack, thereby changing the working directory, but then, when the script exits (for whatever reason, including failure), the trap will run popd , restoring the current working directory before it was executed.这会将源文件的目录推送到导航堆栈,从而更改工作目录,但是,当脚本退出时(无论出于何种原因,包括失败), trap将运行popd ,在执行之前恢复当前工作目录. If the script were to cd and then fail, your terminal could be left in an unpredictable state after the execution ends - the trap prevents this.如果脚本cd然后失败,则您的终端在执行结束后可能会处于不可预测的状态 - 陷阱会阻止这种情况。

echo $PWD

PWD 是一个环境变量。

If you just need to print present working directory then you can follow this.如果您只需要打印当前工作目录,那么您可以按照此操作。

$ vim test

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

Give execute permission:赋予执行权限:

chmod u+x test

Then execute the script by ./test then you can see the present working directory.然后通过./test执行脚本就可以看到当前的工作目录了。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM