首页 > 解决方案 > 如何获得完整的路径,*允许*符号链接

问题描述

我编写了接受目录名称作为参数的 bash 脚本。一个点 ('.') 是一个有效的目录名,但我有时需要知道 '.' 在哪里 是。readlinkand命令提供了一个解析的realpath路径,这没有帮助,因为我需要允许符号链接。

例如,给定目录的解析路径可能类似于/mnt/vol_01/and/then/some,而脚本以 '.' 调用。在哪里 '。' 是/app/then/some(一个符号链接,可以解析到我给出的第一条路径)。

我为解决我的问题所做的就是使用cdpwd组合来提供我想要的完整路径,到目前为止它似乎运行良好。

脚本的简化示例:

DEST_DIR=$1

# Convert the given destination directory to a full path, ALLOWING 
# for symbolic links.  This is necessary in cases where '.' is 
# given as the destination directory.
DEST_DIR=$(cd $DEST_DIR && pwd -L)

# Do stuff in $DEST_DIR

我的问题是:是我使用cdpwd获得我想要的东西的最佳方式吗?或者,还有更好的方法?

标签: bashpathsymlinkrealpathreadlink

解决方案


如果您要做的只是创建一个相对路径更改最小的绝对路径,那么一个简单、安全且快速的方法是:

[[ $dest_dir == /* ]] || dest_dir=$PWD/$dest_dir

(请参阅正确的 Bash 和 shell 脚本变量大写,了解为什么dest_dir比 . 更可取DEST_DIR。)

即使目录不存在(尚)或不可能cd(例如,因为它的权限不允许),上面的代码也将起作用。它可能会产生带有冗余 '.' 的路径。组件、'..' 组件和多余的斜杠(`/a//b'、'//a/b/'、...)。

如果您想要一个最少清理的路径(使符号链接未解析),那么原始代码的修改版本可能是一个合理的选择:

dest_dir=$(cd -- "$dest_dir"/ && pwd)
  • 处理以“-”开头的--目录名是必需的。
  • 中的引号"$dest_dir"是处理包含空格(实际上是$IFS字符)或全局字符的名称所必需的。
  • 结尾的斜杠"$dest_dir"/对于处理相对名称为 simple 的目录是必需的-
  • Plainpwd就足够了,因为它的行为就像-L是默认指定的一样。

请注意,如果失败,代码将设置dest_dir为空字符串。cd您可能想在对变量执行任何其他操作之前检查这一点。

另请注意,这$(cd ...)将使用 Bash 创建一个子 shell。这在一方面是好的,因为之后不需要cd回到起始目录(这可能是不可能的),但如果你经常这样做(例如在循环中),它可能会导致性能问题。

最后,请注意,如果目录名称包含一个或多个尾随换行符(例如由 创建的),则代码将不起作用mkdir $'dir\n'。有可能解决这个问题(如果你真的关心它),但它很混乱。请参阅如何避免 bash 命令替换以删除换行符?shell:在命令替换中保留尾随换行符 ('\n')。一种可能的方法是:

dest_dir=$(cd -- "$dest_dir"/ && printf '%s.' "$PWD")    # Add a trailing '.'
dest_dir=${dest_dir%.}                                   # Remove the trailing '.'

推荐阅读