如何获取完整的PATH,*允许*用于符号链接

问题描述 投票:1回答:1

我编写了接受目录名作为参数的bash脚本。单点('。')是一个有效的目录名称,但我有时需要知道'。'的位置。是。 readlinkrealpath命令提供了一个解决的路径,这没有用,因为我需要允许符号链接。

例如,给定目录的已解析路径可能类似于/mnt/vol_01/and/then/some,而脚本则使用“。”调用。在哪里'。'是/app/then/some(sym链接将解析我给出的第一条路径)。

我为解决我的问题所做的是使用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是获得我想要的最佳方式吗?或者,还有更好的方法?

bash path symlink realpath readlink
1个回答
1
投票

如果你想要做的就是创建一个绝对路径,从相对路径获得最小的变化,那么一个简单,安全,快速的方法是:

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

(请参阅Correct Bash and shell script variable capitalization,了解为什么dest_dir优于DEST_DIR。)

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

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

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

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

另请注意,$(cd ...)将使用Bash创建子shell。这在某种程度上是好的,因为之后不需要cd回到起始目录(这可能是不可能的),但如果你做了很多事情(例如在循环中)它可能会导致性能问题。

最后,请注意,如果目录名称包含一个或多个尾随换行符(例如由mkdir $'dir\n'创建),则代码将不起作用。有可能解决问题(如果你真的关心它),但它很混乱。见How to avoid bash command substitution to remove the newline character?shell: keep trailing newlines ('\n') in command substitution。一种可行的方法是:

dest_dir=$(cd -- "$dest_dir"/ && printf '%s.' "$PWD")    # Add a trailing '.'
dest_dir=${dest_dir%.}                                   # Remove the trailing '.'
© www.soinside.com 2019 - 2024. All rights reserved.