我编写了接受目录名作为参数的bash脚本。单点('。')是一个有效的目录名称,但我有时需要知道'。'的位置。是。 readlink
和realpath
命令提供了一个解决的路径,这没有用,因为我需要允许符号链接。
例如,给定目录的已解析路径可能类似于/mnt/vol_01/and/then/some
,而脚本则使用“。”调用。在哪里'。'是/app/then/some
(sym链接将解析我给出的第一条路径)。
我为解决我的问题所做的是使用cd
和pwd
组合来提供我想要的完整路径,到目前为止它似乎工作正常。
脚本的简化示例:
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
我的问题是:我使用cd
和pwd
是获得我想要的最佳方式吗?或者,还有更好的方法?
如果你想要做的就是创建一个绝对路径,从相对路径获得最小的变化,那么一个简单,安全,快速的方法是:
[[ $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 '.'