问题:是否有一个简单的sh/bash/zsh/fish/...命令来打印我提供的文件的绝对路径?
用例:我在目录中/a/b
,我想c
在命令行上打印文件的完整路径,以便我可以轻松地将其粘贴到另一个程序中:/a/b/c
.简单但是一个小程序可以在处理长路径时节省大约5秒钟,这最终会增加.因此,令我惊讶的是,我无法找到标准实用程序来执行此操作 - 真的没有吗?
这是一个示例实现,abspath.py:
#!/usr/bin/python # Author: Diggory Hardy# 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)
Benjamin Ban.. 490
试试realpath
.
$ realpath example.txt /home/username/example.txt
+1,非常好的程序.但请注意,它是一个外部命令(不是内置的shell),默认情况下可能不会出现在每个系统中,即您可能需要安装它.在Debian中,它位于一个具有相同名称的单独包中. (123认同)
@Dalin:尝试安装coreutils.二进制文件名为grealpath. (14认同)
我在我的路径中添加了一个`realpath`,其中包括:https://github.com/westonruter/misc-cli-tools/blob/master/realpath (5认同)
这个工具是在GNU coreutils 8.15(2012年)中引入的,所以它很新. (4认同)
如果传递的文件名不存在,则不起作用. (3认同)
Paused until.. 301
尝试readlink
解决符号链接:
readlink -e /foo/bar/baz
我宁愿使用'-f'而不是'-e',以便我们可以看到不存在的文件的绝对路径. (47认同)
在我看来,`-m`是最好的选择. (13认同)
@iconoclast这些选项在OSX上不可用,并且根据BSD"readlink"联机帮助页:`只打印符号链接的目标.如果给定的参数不是符号链接,readlink将不打印任何内容并退出并显示错误`,因此readlink在OSX上不能用于此目的 (11认同)
这看起来对我来说最简单,同时也是便携式的.readlink是gnu coreutils的端口,因此它几乎可以安装在任何Linux发行版上,除了一些嵌入式发行版. (5认同)
dogbane.. 240
#! /bin/sh echo "$(cd "$(dirname "$1")"; pwd -P)/$(basename "$1")"
到目前为止唯一的POSIX解决方案不需要您编写和编译可执行文件,因为readlink和realpath不是POSIX (29认同)
我使用`function realpath {echo $(cd $(dirname $ 1); pwd)/ $(basename $ 1); 在OS X上让自己成为一个`realpath`命令(目前接受的答案).谢谢! (21认同)
不要忘记引用所有的东西.如果你不明白为什么,试试你的程序文件`ab`(a和b之间的两个空格,SO吃其中一个). (7认同)
peterh.. 78
忘掉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")
该解决方案利用了这样一个事实:pwd
当没有参数调用时,Bash内置命令将打印当前目录的绝对路径.
它是便携式的,不需要也不readlink
或realpath
经常不上的默认安装中存在一个给定的Linux/Unix发行版.
如上所述,如果给定的目录路径不存在,函数将失败并在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 }
我想补充一点,`realpath`来自coreutils包,它还包含诸如`who`,`touch`或`cat`等工具.它是相当标准的GNU工具集,所以你可以肯定它几乎安装在任何基于Linux的机器上.那么说,你是对的:它有2个问题:i)你可能会错过它在默认安装上非GNU unix系统(如OpenBSD)ii)这个工具是在8.15版本中引入的(所以从2012年开始它是相当新的),所以你会在长期稳定的系统(如RHEL 6)上错过它. (3认同)
@marbu realpath不存在于Ubuntu 14.04或Debian Wheezy上.随着时间的推移它可能会变得有些标准,但现在肯定不是.另请注意,OP没有提及有关linux或GNU的任何内容.Bash比这更广泛地使用. (3认同)
Flimm.. 75
$ readlink -m FILE /path/to/FILE
这比readlink -e FILE
or好realpath
,因为即使文件不存在也能正常工作.
试试realpath
.
$ realpath example.txt /home/username/example.txt
尝试readlink
解决符号链接:
readlink -e /foo/bar/baz
#! /bin/sh echo "$(cd "$(dirname "$1")"; pwd -P)/$(basename "$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")
该解决方案利用了这样一个事实:pwd
当没有参数调用时,Bash内置命令将打印当前目录的绝对路径.
它是便携式的,不需要也不readlink
或realpath
经常不上的默认安装中存在一个给定的Linux/Unix发行版.
如上所述,如果给定的目录路径不存在,函数将失败并在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 }
$ readlink -m FILE /path/to/FILE
这比readlink -e FILE
or好realpath
,因为即使文件不存在也能正常工作.
这个绝对路径转换器shell函数的相对路径
不需要实用程序(只是cd
和pwd
)
适用于目录和文件
处理..
和.
处理dir或文件名中的空格
要求文件或目录存在
如果给定路径上不存在任何内容,则不返回任
处理绝对路径作为输入(基本上通过它们)
码:
function abspath() { # generate absolute path from relative path # $1 : relative filename # return : absolute path if [ -d "$1" ]; then # dir (cd "$1"; pwd) elif [ -f "$1" ]; then # file if [[ $1 = /* ]]; then echo "$1" elif [[ $1 == */* ]]; then echo "$(cd "${1%/*}"; pwd)/${1##*/}" else echo "$(pwd)/$1" fi fi }
样品:
# assume inside /parent/cur abspath file.txt => /parent/cur/file.txt abspath . => /parent/cur abspath .. => /parent abspath ../dir/file.txt => /parent/dir/file.txt abspath ../dir/../dir => /parent/dir # anything cd can handle abspath doesnotexist => # empty result if file/dir does not exist abspath /file.txt => /file.txt # handle absolute path input
注意:这是基于nolan6000和bsingh的答案,但修复了文件大小写.
我也理解原始问题是关于现有的命令行实用程序.但是因为这似乎是stackoverflow的问题,包括想要具有最小依赖性的shell脚本,我把这个脚本解决方案放在这里,所以我可以在以后找到它:)
该find
命令可能有所帮助
find $PWD -name ex* find $PWD -name example.log
列出当前目录中或下面的所有文件,其名称与模式匹配.如果您只获得一些结果(例如,包含少量文件的树底部附近的目录),您可以简化它
find $PWD
我在Solaris 10上使用它,它没有提到的其他实用程序.
如果你没有readlink或realpath实用程序,你可以使用在bash和zsh中工作的以下函数(不确定其余部分).
abspath () { case "$1" in /*)printf "%s\n" "$1";; *)printf "%s\n" "$PWD/$1";; esac; }
这也适用于不存在的文件(与python函数一样os.path.abspath
).
不幸的abspath ./../somefile
是没有摆脱点.
这是一个zsh-only函数,我喜欢它的紧凑性.它使用'A'扩展修饰符 - 参见zshexpn(1).
realpath() { for f in "$@"; do echo ${f}(:A); done }
一般没有这样的事情的 absolute path
一个文件(这个声明意味着,可能有一个以上的一般,因此使用了定冠词的是不恰当的).An absolute path
是从根"/"开始的任何路径,并且指定一个没有歧义的文件,独立于工作目录.(例如参见维基百科).
A relative path
是从另一个目录开始解释的路径.它可能是工作目录,如果它是relative path
由应用程序操纵(虽然不一定).当它在目录中的符号链接中时,通常旨在相对于该目录(尽管用户可能还有其他用途).
因此,绝对路径只是相对于根目录的路径.
路径(绝对路径或相对路径)可能包含也可能不包含符号链接.如果不是这样,它在某种程度上也不受链接结构变化的影响,但这不是必需的,甚至不是必需的.有人叫canonical path
(或canonical file name
或resolved path
)的absolute path
其中所有符号链接都得到了解决,即通过向whetever它们链接到的路径已被替换.命令realpath
和readlink
两者都寻找规范路径,但只有realpath
一个选项来获取绝对路径而不必费心解析符号链接(以及其他几个选项来获取各种路径,绝对或相对于某个目录).
这需要几个评论:
如果已经创建了它们应该链接到的任何内容,则只能解析符号链接,这显然并非总是如此.命令realpath
并readlink
有选项来解释它.
路径上的目录以后可以成为符号链接,这意味着路径不再存在canonical
.因此,概念是时间(或环境)依赖.
即使在理想情况下,当所有符号链接都可以解析时,canonical path
文件可能仍然不止一个,原因有两个:
包含该文件的分区可能已同时(ro
)挂载在几个挂载点上.
可能存在到文件的硬链接,这意味着该文件基本上存在于几个不同的目录中.
因此,即使有更严格的定义canonical path
,也可能存在一些文件的规范路径.这也意味着限定符canonical
有些不足,因为它通常意味着唯一性的概念.
这扩展了对该主题的简短讨论,以回答Bash中的另一个类似问题:检索给定相对的绝对路径
我的结论是,realpath
设计更好,更灵活readlink
.如果没有选项返回符号链接的值readlink
,则不会使用它的唯一用途realpath
.