如何获得完整的路径,*允许*用于符号链接

时间:2019-02-19 16:14:36

标签: bash path symlink realpath readlink

我编写了bash脚本,这些脚本接受目录名称作为参数。单点('。')是有效的目录名称,但是有时我需要知道'。'在哪里。是。 readlinkrealpath命令提供了一个已解析的路径,这无济于事,因为我需要允许符号链接。

例如,给定目录的解析路径可能类似于/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是获得我想要的东西的最好方法吗?还是有更好的方法?

1 个答案:

答案 0 :(得分:1)

如果您要做的就是创建一条相对路径,该相对路径的变化最小,那么一种简单,安全,快速的方法就是:

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

(请参见Correct Bash and shell script variable capitalization,以了解为什么dest_dirDEST_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回到起始目录(这可能是不可能的),但是如果您做很多(例如循环),可能会导致性能问题。 / p>

最后,请注意,如果目录名称包含一个或多个结尾的换行符(例如,由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 '.'