bash / fish命令打印文件的绝对path
问题:是否有一个简单的sh / bash / zsh / fish / …命令来打印我提供的文件的绝对path?
用例:我在/a/b目录下,我想在命令行上打印文件c的完整path,以便我可以轻松地将它粘贴到另一个程序: /a/b/c 。 简单,但一个小程序来做到这一点可能会节省我5秒左右的时间来处理长path,最后加起来。 所以我很惊讶,我找不到一个标准的工具来做到这一点 – 真的没有? 
这是一个示例实现,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) 
	
 尝试realpath 。 
 ~ $ realpath .bashrc /home/username/.bashrc 
 尝试readlink这将解决符号链接: 
 readlink -e /foo/bar/baz 
 #! /bin/sh echo "$(cd "$(dirname "$1")"; pwd)/$(basename "$1")" 
 $ readlink -m FILE /path/to/FILE 
 这比readlink -e FILE或realpath更好,因为即使文件不存在,它也可以工作。 
 忘记您的系统上可能安装或不安装的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") 
如何和为什么它的工作?
 该解决scheme利用了Bash内置的pwd命令在调用不带参数的情况下将打印当前目录的绝对path的事实。 
为什么我喜欢这个解决scheme?
 它是可移植的,不需要readlink或readlink ,这通常在给定的Linux / Unix发行版的默认安装上不存在。 
如果dir不存在呢?
如上所述,如果给定的目录path不存在,该函数将失败并在stderr上打印。 这可能不是你想要的。 您可以扩展function来处理这种情况:
 #!/bin/bash get_abs_filename() { # $1 : relative filename if [ -d "$(dirname "$1")" ]; then echo "$(cd "$(dirname "$1")" && pwd)/$(basename "$1")" fi } 
现在,如果父目录不存在,它将返回一个空string。
你如何处理尾随“..”或“。” 在input?
那么,在这种情况下它确实给出了一个绝对path,但不是最小的path。 它会看起来像:
 /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 } 
这个绝对path转换器shell函数的相对path
-  不需要工具(只需cd和pwd)
- 适用于目录和文件
-  处理..和.
- 处理dir或文件名中的空格
- 需要该文件或目录存在
- 如果在给定的path上不存在,则不返回任何内容
- 处理绝对path作为input(实质上传递它们)
码:
 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的答案,但修复了文件大小写。
我也明白,原来的问题是关于现有的命令行工具。 但是,因为这似乎是在包括希望有最小的依赖关系的shell脚本的stackoverflow的问题,我把这个脚本解决scheme在这里,所以我可以find它以后:)
  find命令可能会有所帮助 
 find $PWD -name ex* find $PWD -name example.log 
列出名称与模式匹配的当前目录中或下面的所有文件。 如果只能得到一些结果(例如,包含less量文件的树底部的目录),则可以简化它
 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-onlyfunction,我喜欢它的紧凑性。 它使用“A”扩展修饰符 – 请参阅zshexpn(1)。
 realpath() { for f in "$@"; do echo ${f}(:A); done } 
 通常没有文件的 absolute path (这个语句意味着一般可能有多于一个,因此使用定冠词是不合适的)。  absolute path是从根“/”开始的任何path,并且独立于工作目录指定一个没有歧义的文件(参见例如维基百科 )。 
  relative path是从另一个目录开始解释的path。 它可能是工作目录,如果它是由应用程序操作的relative path (尽pipe不一定)。 当它在一个目录中的符号链接中时,通常打算与该目录相关(尽pipe用户可能有其他用途)。 
因此绝对path只是相对于根目录的path。
 path(绝对或相对)可以包含或不包含符号链接。 如果没有,连接结构的变化也是有些不可避免的,但这不是必需的,甚至是不可取的。 有些人称canonical path (或canonical file name或resolved path )为absolute path ,其中所有符号链接已经被parsing,即已经被链接到的path取代。  realpath和readlink命令都查找规范path,但是只有实际path才有获得绝对path的选项,而不会打扰parsing符号链接(以及其他几个选项来获取各种path,绝对或相对于某个目录)。 
这需要几个说法:
-  象征性的链接只有在它们应该链接的链接已经被创build的时候才能被解决,这显然并不总是这样。  realpath和readlink命令可以解释这个问题。
-  path上的目录后来可以成为符号链接,这意味着path不再是canonical。 因此,这个概念是时间(或环境)的依赖。
-  即使在理想的情况下,当所有符号链接都可以解决时,仍然可能存在不止一个canonical path的文件canonical path,原因有二:-  包含该文件的分区可能已同时安装( ro)在多个安装点上。
- 有可能是硬链接到文件,这意味着文件存在于几个不同的目录。
 
-  包含该文件的分区可能已同时安装( 
 因此,即使canonical path限制性更严格,也可能有几条规范的文件path。 这也意味着canonical性有些不足,因为它通常意味着唯一性的概念。 
这就在Bash的另一个类似问题的答案中扩展了关于该主题的简要讨论:检索给定相对的绝对path
 我的结论是realpath的devise更好,比readlink更灵活。 只有readlink没有被realpath覆盖的用途是调用没有选项返回符号链接的值。 
我将下面的脚本放在我的系统上,我把它叫做bash别名,当我想快速获取当前目录中文件的完整path时:
 #!/bin/bash /usr/bin/find "$PWD" -maxdepth 1 -mindepth 1 -name "$1" 
我不知道为什么,但是,当在脚本“$ PWD”调用的OS X上扩展到绝对path。 在命令行中调用find命令时,不会。 但它做我想要的…享受。
 对于目录dirname获取../并返回./ 。 
nolan6000的function可以修改,以解决:
 get_abs_filename() { # $1 : relative filename if [ -d "${1%/*}" ]; then echo "$(cd ${1%/*}; pwd)/${1##*/}" fi } 
 #! /bin/bash file="$@" realpath "$file" 2>/dev/null || eval realpath $(echo $file | sed 's/ /\\ /g') 
 这弥补了realpath的缺点,将其存储在shell脚本fullpath 。 你现在可以打电话给: 
 $ cd && touch a\ a && rm A 2>/dev/null $ fullpath "aa" /home/user/aa $ fullpath ~/a\ a /home/user/aa $ fullpath A A: No such file or directory. 
这不是对这个问题的回答,但对于那些做脚本的人来说:
 echo `cd "$1" 2>/dev/null&&pwd||(cd "$(dirname "$1")";pwd|sed "s|/*\$|/${1##*/}|")` 
它正确处理/ .. ./等。 我似乎也在OSX上工作
在Ruby中获得绝对path的另一种方法是:
 realpath() {ruby -e "require 'Pathname'; puts Pathname.new('$1').realpath.to_s";} 
无参数(当前文件夹)和相对和绝对文件或文件夹path作为agument工作。
 与描述的dogbane 答案是什么来的: 
 #! /bin/sh echo "$(cd "$(dirname "$1")"; pwd)/$(basename "$1")" 
说明:
-  这个脚本获取相对path作为参数"$1"
-  然后我们得到该path的dirname部分(您可以将dir或文件传递给此脚本): dirname "$1"
-  然后我们把cd "$(dirname "$1")放到这个相对的目录中,并通过运行pwdshell命令获得它的绝对path
-  之后,我们将基本名称追加到绝对path: $(basename "$1")
-  作为最后一步,我们echo它
 嘿家伙,我知道这是一个古老的线程,但我只是张贴这个参考谁访问这个像我一样的其他人。 如果我正确地理解了这个问题,我想locate $filename命令。 它显示提供的文件的绝对path,但只有存在的话。