AskOverflow.Dev

AskOverflow.Dev Logo AskOverflow.Dev Logo

AskOverflow.Dev Navigation

  • 主页
  • 系统&网络
  • Ubuntu
  • Unix
  • DBA
  • Computer
  • Coding
  • LangChain

Mobile menu

Close
  • 主页
  • 系统&网络
    • 最新
    • 热门
    • 标签
  • Ubuntu
    • 最新
    • 热门
    • 标签
  • Unix
    • 最新
    • 标签
  • DBA
    • 最新
    • 标签
  • Computer
    • 最新
    • 标签
  • Coding
    • 最新
    • 标签
主页 / unix / 问题 / 788467
Accepted
villapx
villapx
Asked: 2024-12-21 01:17:10 +0800 CST2024-12-21 01:17:10 +0800 CST 2024-12-21 01:17:10 +0800 CST

`cd && pwd` 与 `dirname` 的优缺点

  • 772

我的一些同事喜欢在他们的 BASH 脚本顶部写以下内容来确定包含该脚本的目录:

SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"

而我则倾向于以下做法:

SCRIPT_DIR="$(dirname "${BASH_SOURCE[0]}")"

(请注意,在大多数情况下,我们并不关心解析符号链接,因此我们倾向于使用这些而不是例如readlink)


cd ... && pwd与 -only 方法相比,该方法有什么优点dirname吗?它似乎只是执行了额外的步骤来实现完全相同的结果,但我想确保我没有遗漏任何细微差别。

bash
  • 2 2 个回答
  • 1315 Views

2 个回答

  • Voted
  1. Best Answer
    Stéphane Chazelas
    2024-12-21T01:45:01+08:002024-12-21T01:45:01+08:00

    要点:

    SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
    

    更确切地说应该是:

    SCRIPT_DIR=$(
      CDPATH= cd -P -- "$(dirname -- "$BASH_SOURCE")" && pwd
    )
    

    它为您提供了一个绝对路径(以及-P,规范的绝对路径,realpath()),而$BASH_SOURCE(在 bash 中$var是 的缩写,${var[0]}就像在 ksh 中一样)很可能是一个相对路径,例如../file.bash。

    如果没有-P,在 的情况下../file.bash,cd ..很可能会将您带到与脚本默认所在的目录不同的目录(再次像在 ksh 中引入了(mis)功能)cd进行逻辑遍历,其中cd ..没有chdir("..")而是chdir(dirname($PWD))(并且$PWD将具有符号链接组件,如果您cd之前已经进入带有符号链接组件的路径)。

    我们将其设置CDPATH为空字符串(就其cd而言,这相当于取消设置),以防它被设置为其他内容,例如,环境中有一个同名变量,否则cd带有相对路径(如本例所示BASH_SOURCE=dir/file.bash)的变量可能会将您带到其他地方。CDPATH全局取消设置可能是一个好主意,但如果该脚本旨在被引用,则可能不可接受。

    请注意,如果 的目录名BASH_SOURCE或其实际路径以换行符结尾(因为命令替换会删除所有dirname尾随的换行符,而不仅仅是/pwd为输出添加的换行符),或者例如 (因为是$BASH_SOURCE的缩写),它仍然无法正常工作。-/filecd -cd -- "$OLDPWD"

    解决后者的问题,更普遍地讲,更接近cd非chdir()shell 编程语言中发现的问题,可以使用POSIX 建议的辅助函数来实现:

    chdir() case $1 in
      (/*) cd -P "$1";;
      ('') echo>&2 'Directory is an empty string'; return 1;;
      ( *) CDPATH= cd -P "./$1";;
    esac
    

    相对路径前缀为./可避免需要--,并解决与不解释为上一个目录相反的-问题。请参阅此处了解为什么对空字符串进行特殊处理。该前缀还会禁用处理,因此除了提醒该帮助程序禁用处理之外,不需要上述内容。./--./CDPATHCDPATH=chdirCDPATH

    在 zsh 中,你只需执行以下操作:

    SCRIPT_DIR=$0:h:P
    

    或者:

    SCRIPT_DIR=$0:P:h
    

    其中:P为您提供realpath()和:h头部(目录名,类似于 csh)。

    $0如果恰好是符号链接本身,则两者都不一定会给出相同的结果。

    这些不存在上述 bash 方法的任何问题。

    • 15
  2. terdon
    2024-12-21T01:27:25+08:002024-12-21T01:27:25+08:00

    坦率地说,我认为这两者都是不必要的复杂(我错了;请参阅Stéphane 的回答,其中解释了如果您需要解析绝对路径,这就是这样做的方法)。即使是更简单的版本仍然会调用不需要的外部命令。为什么不直接这样做:

    script_dir="${BASH_SOURCE%/*}"
    

    至于这两个命令,我认为使用两个外部命令这种更加复杂的方法没有任何好处。pwd如果可以使用,为什么要运行$PWD,但为什么要运行这么多命令呢?如果您需要解析符号链接,那么我可以理解引入外部命令,但对于像这样简单的事情呢?

    现在,有些极端情况会导致此方法失效。正如 Stéphane Chazelas 在一条(现已删除)评论中解释的那样:

    file.bash如果$BASH_SOURCE是 则返回(file.bashwhiledirname会返回),如果是 则返回.空字符串(where会返回)。$BASH_SOURCE/file.bashdirname/

    这是否与您的情况相关只有您自己知道。


    另外,你真的不想使用大写字母作为 shell 变量名。因为按照惯例,全局环境变量是大写的,所以将大写字母用于你自己的局部变量是一种不好的做法,因为这会导致命名冲突和难以发现错误。

    • 11

相关问题

  • 通过命令的标准输出以编程方式导出环境变量[重复]

  • 从文本文件传递变量的奇怪问题

  • 虽然行读取保持转义空间?

  • `tee` 和 `bash` 进程替换顺序

  • 运行一个非常慢的脚本直到它成功

Sidebar

Stats

  • 问题 205573
  • 回答 270741
  • 最佳答案 135370
  • 用户 68524
  • 热门
  • 回答
  • Marko Smith

    模块 i915 可能缺少固件 /lib/firmware/i915/*

    • 3 个回答
  • Marko Smith

    无法获取 jessie backports 存储库

    • 4 个回答
  • Marko Smith

    如何将 GPG 私钥和公钥导出到文件

    • 4 个回答
  • Marko Smith

    我们如何运行存储在变量中的命令?

    • 5 个回答
  • Marko Smith

    如何配置 systemd-resolved 和 systemd-networkd 以使用本地 DNS 服务器来解析本地域和远程 DNS 服务器来解析远程域?

    • 3 个回答
  • Marko Smith

    dist-upgrade 后 Kali Linux 中的 apt-get update 错误 [重复]

    • 2 个回答
  • Marko Smith

    如何从 systemctl 服务日志中查看最新的 x 行

    • 5 个回答
  • Marko Smith

    Nano - 跳转到文件末尾

    • 8 个回答
  • Marko Smith

    grub 错误:你需要先加载内核

    • 4 个回答
  • Marko Smith

    如何下载软件包而不是使用 apt-get 命令安装它?

    • 7 个回答
  • Martin Hope
    user12345 无法获取 jessie backports 存储库 2019-03-27 04:39:28 +0800 CST
  • Martin Hope
    Carl 为什么大多数 systemd 示例都包含 WantedBy=multi-user.target? 2019-03-15 11:49:25 +0800 CST
  • Martin Hope
    rocky 如何将 GPG 私钥和公钥导出到文件 2018-11-16 05:36:15 +0800 CST
  • Martin Hope
    Evan Carroll systemctl 状态显示:“状态:降级” 2018-06-03 18:48:17 +0800 CST
  • Martin Hope
    Tim 我们如何运行存储在变量中的命令? 2018-05-21 04:46:29 +0800 CST
  • Martin Hope
    Ankur S 为什么 /dev/null 是一个文件?为什么它的功能不作为一个简单的程序来实现? 2018-04-17 07:28:04 +0800 CST
  • Martin Hope
    user3191334 如何从 systemctl 服务日志中查看最新的 x 行 2018-02-07 00:14:16 +0800 CST
  • Martin Hope
    Marko Pacak Nano - 跳转到文件末尾 2018-02-01 01:53:03 +0800 CST
  • Martin Hope
    Kidburla 为什么真假这么大? 2018-01-26 12:14:47 +0800 CST
  • Martin Hope
    Christos Baziotis 在一个巨大的(70GB)、一行、文本文件中替换字符串 2017-12-30 06:58:33 +0800 CST

热门标签

linux bash debian shell-script text-processing ubuntu centos shell awk ssh

Explore

  • 主页
  • 问题
    • 最新
    • 热门
  • 标签
  • 帮助

Footer

AskOverflow.Dev

关于我们

  • 关于我们
  • 联系我们

Legal Stuff

  • Privacy Policy

Language

  • Pt
  • Server
  • Unix

© 2023 AskOverflow.DEV All Rights Reserve