问题:是否有一个简单的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)
#1楼
我喜欢它的紧凑性,这是仅zsh函数。 它使用'A'扩展修饰符-请参见zshexpn(1)。
realpath() { for f in "$@"; do echo ${f}(:A); done }
#2楼
$ readlink -m FILE
/path/to/FILE
这比readlink -e FILE或realpath更好,因为即使文件不存在也可以工作。
#3楼
一般有作为没有这样的事情absolute path到一个文件中(这个声明意味着,可能有一个以上的一般,因此使用了定冠词the是不恰当的)。 absolute path是从根目录“ /”开始并指定文件的任何路径,而与工作目录无关(例如,参见Wikipedia )。
relative path是要从另一个目录开始解释的路径。 如果它是由应用程序操纵的relative path ,则它可能是工作目录(尽管不一定)。 当它在目录中的符号链接中时,通常应相对于该目录(尽管用户可能会想到其他用途)。
因此,绝对路径只是相对于根目录的路径。
路径(绝对路径或相对路径)可能包含也可能不包含符号链接。 如果不是这样,则在某种程度上也不能改变链接结构,但这不是必须的,甚至是不希望的。 有人将canonical path (或canonical file name或已resolved path )称为absolute path ,其中所有符号链接均已解析,即已被链接到的符号路径所替代。 命令realpath和readlink都在寻找规范的路径,但是只有realpath可以选择获取绝对路径而不必费解解析符号链接(以及其他几种选择来获取各种路径,无论是绝对路径还是相对于某个目录)。
这需要一些说明:
- 仅当已经创建了符号链接时,才可以解析符号链接,这显然并非总是如此。 命令
realpath和readlink具有解决方案。 - 路径上的目录以后可以变成符号链接,这意味着该路径不再
canonical。 因此,该概念取决于时间(或环境)。 - 即使在理想情况下,当所有符号链接都可以解析时,文件的
canonical path仍然可能不止一个,原因有两个:- 包含文件的分区可能已同时(
ro)安装在几个安装点上。 - 可能存在指向该文件的硬链接,这实际上意味着该文件存在于几个不同的目录中。
- 包含文件的分区可能已同时(
因此,即使对canonical path定义要严格得多,文件也可能有多个规范路径。 这也意味着限定词的canonical性不足,因为它通常暗示唯一性的概念。
这扩展了对该主题的简短讨论,并回答了Bash另一个类似的问题:检索给定相对路径的绝对路径
我的结论是,与readlink相比, realpath的设计更好,更灵活。 readlink唯一未包含在realpath中的用途是不带选项返回符号链接值的调用。
#4楼
忘记可能已安装或未安装在系统上的readlink和realpath 。
在这里扩展狗狗的答案 ,它表示为一个函数:
#!/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
}
现在,如果父目录不存在,它将返回一个空字符串。
您如何处理尾随的“ ..”或“。” 在输入?
好吧,在这种情况下,它确实提供了一条绝对的路径,但不是一条最小的路径。 它看起来像:
/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
}
#5楼
对于目录, dirname跳入../并返回./ 。
可以修改nolan6000的功能以修复以下问题:
get_abs_filename() {
# $1 : relative filename
if [ -d "${1%/*}" ]; then
echo "$(cd ${1%/*}; pwd)/${1##*/}"
fi
}
来源:oschina
链接:https://my.oschina.net/stackoom/blog/3164074