问:有没有简单的sh/bash/zsh/fish/…命令打印任何文件的绝对路径我馈送它?
用例:我在目录/a/b中,我想在命令行上打印文件c的完整路径,这样我就可以轻松地将它粘贴到另一个程序:/a/b/c中。这很简单,但是在处理长路径时,一个小程序可能会为我节省5秒左右的时间。因此,让我感到惊讶的是,我找不到一个标准的实用程序来做这件事——真的没有吗?
下面是一个示例实现,abspath.py:
#!/usr/bin/python
# Author: Diggory Hardy <diggory.hardy@gmail.com>
# Licence: public domain
# Purpose: print the absolute path of all input paths
import sys
import os.path
if len(sys.argv)>1:
for i in range(1,len(sys.argv)):
print os.path.abspath( sys.argv[i] )
sys.exit(0)
else:
print >> sys.stderr, "Usage: ",sys.argv[0]," PATH."
sys.exit(1)
忘记readlink和realpath,它们可能安装也可能不安装在您的系统上。
在上面扩展dogbane的答案,它被表示为一个函数:
#!/bin/bash
get_abs_filename() {
# $1 : relative filename
echo "$(cd "$(dirname "$1")" && pwd)/$(basename "$1")"
}
然后你可以这样使用它:
myabsfile=$(get_abs_filename "../../foo/bar/file.txt")
它是如何工作的,为什么工作?
该解决方案利用了这样一个事实,即Bash内置的pwd命令在调用时不带参数地打印当前目录的绝对路径。
为什么我喜欢这个解?
它是可移植的,并且不需要readlink或realpath,这在给定的Linux/Unix发行版的默认安装中通常不存在。
如果dir不存在呢?
如上所述,如果给定的目录路径不存在,该函数将失败并在stderr上打印。这可能不是你想要的。你可以展开函数来处理这种情况:
#!/bin/bash
get_abs_filename() {
# $1 : relative filename
if [ -d "$(dirname "$1")" ]; then
echo "$(cd "$(dirname "$1")" && pwd)/$(basename "$1")"
fi
}
现在如果父dirs不存在,它将返回一个空字符串。
你如何处理拖尾?'或'。输入?
在这种情况下,它确实给出了一条绝对路径,但不是最小路径。它看起来像:
/Users/bob/Documents/..
如果您想解决'..你需要把脚本写成这样:
get_abs_filename() {
# $1 : relative filename
filename=$1
parentdir=$(dirname "${filename}")
if [ -d "${filename}" ]; then
echo "$(cd "${filename}" && pwd)"
elif [ -d "${parentdir}" ]; then
echo "$(cd "${parentdir}" && pwd)/$(basename "${filename}")"
fi
}
通常不存在文件的绝对路径(这句话的意思是通常可能有多个路径,因此使用定冠词the是不合适的)。绝对路径是从根“/”开始的任何路径,并且与工作目录无关地指定文件。(参见维基百科)。
相对路径是从另一个目录开始解释的路径。如果它是应用程序操作的相对路径,则它可能是工作目录
(虽然不一定)。当它位于目录中的符号链接中时,通常打算相对于该目录(尽管用户可能有其他用途)。
因此,绝对路径只是相对于根目录的路径。
A path (absolute or relative) may or may not contain symbolic links. If it does not, it is also somewhat impervious to changes in the linking structure, but this is not necessarily required or even desirable. Some people call canonical path ( or canonical file name or resolved path) an absolute path in which all symbolic links have been resolved, i.e. have been replaced by a path to whetever they link to. The commands realpath and readlink both look for a canonical path, but only realpath has an option for getting an absolute path without bothering to resolve symbolic links (along with several other options to get various kind of paths, absolute or relative to some directory).
这里有几点需要说明:
symbolic links can only be resolved if whatever they are supposed to
link to is already created, which is obviously not always the case. The commands realpath and readlink have options to account for that.
a directory on a path can later become a symbolic link, which means that the path is no longer canonical. Hence the concept is time (or environment) dependent.
even in the ideal case, when all symbolic links can be resolved,
there may still be more than one canonical path to a file, for two
reasons:
the partition containing the file may have been mounted simultaneously (ro) on several mount points.
there may be hard links to the file, meaning essentially the the file exists in several different directories.
因此,即使使用更严格的规范路径定义,一个文件也可能有多个规范路径。这也意味着限定符规范是不适当的,因为它通常意味着唯一性的概念。
这将在Bash上回答另一个类似问题时扩展对该主题的简短讨论:检索给定相对的绝对路径
我的结论是,realpath比readlink设计得更好,也更灵活。
readlink唯一没有被realpath覆盖的用法是没有返回符号链接值的选项的调用。