问:有没有简单的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)

当前回答

在某些情况下,这个问题最上面的答案可能具有误导性。假设你要查找的文件的绝对路径在$ path变量中:

# node is in $PATH variable
type -P node
# /home/user/.asdf/shims/node
cd /tmp
touch node  # But because there is a file with the same name inside the current dir check out what happens below
readlink -e node
# /tmp/node
readlink -m node
# /tmp/node
readlink -f node
# /tmp/node
echo "$(cd "$(dirname "node")"; pwd -P)/$(basename "node")"
# /tmp/node
realpath node
# /tmp/node
realpath -e node
# /tmp/node

# Now let's say that for some reason node does not exist in current directory
rm node
readlink -e node
# <nothing printed>
readlink -m node    
# /tmp/node         # Note: /tmp/node does not exist, but is printed
readlink -f node
# /tmp/node         # Note: /tmp/node does not exist, but is printed
echo "$(cd "$(dirname "node")"; pwd -P)/$(basename "node")"
# /tmp/node         # Note: /tmp/node does not exist, but is printed
realpath node
# /tmp/node         # Note: /tmp/node does not exist, but is printed
realpath -e node
# realpath: node: No such file or directory

基于以上,我可以得出结论:realpath -e和readlink -e可以用于查找文件的绝对路径,我们期望存在于当前目录中,而不受$ path变量的影响。唯一的区别是realpath输出到stderr,但如果没有找到file,两者都会返回错误代码:

cd /tmp
rm node
realpath -e node ; echo $?
# realpath: node: No such file or directory
# 1
readlink -e node ; echo $?
# 1

现在,如果您想要一个存在于$ path中的文件的绝对路径a,那么下面的命令将是合适的,这与当前目录中是否存在同名文件无关。

type -P example.txt
# /path/to/example.txt

# Or if you want to follow links
readlink -e $(type -P example.txt)
# /originalpath/to/example.txt

# If the file you are looking for is an executable (and wrap again through `readlink -e` for following links )
which executablefile
# /opt/bin/executablefile

如果没有,回退到$PATH,示例:

cd /tmp
touch node
echo $(readlink -e node || type -P node)
# /tmp/node
rm node
echo $(readlink -e node || type -P node)
# /home/user/.asdf/shims/node

其他回答

如果你没有readlink或realpath实用工具,那么你可以使用下面的函数,它可以在bash和zsh中工作(不确定其他的)。

abspath () { case "$1" in /*)printf "%s\n" "$1";; *)printf "%s\n" "$PWD/$1";; esac; }

这也适用于不存在的文件(就像python函数os.path.abspath)。

不幸的是,沐浴。/somefile不能去掉圆点。

通常不存在文件的绝对路径(这句话的意思是通常可能有多个路径,因此使用定冠词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覆盖的用法是没有返回符号链接值的选项的调用。

这个相对路径到绝对路径转换器的壳函数

不需要任何工具(只需要CD和pwd) 适用于目录和文件 处理. .和。 处理目录或文件名中的空格 要求文件或目录存在 如果给定路径上不存在,则返回零 将绝对路径作为输入处理(基本上是传递它们)

代码:

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脚本,希望有最小的依赖关系,我把这个脚本解决方案放在这里,所以我可以稍后找到它:)

嘿,伙计们,我知道这是一个旧帖子,但我只是发布这个帖子供其他像我一样访问这个帖子的人参考。如果我正确理解了这个问题,我认为是locate $filename命令。它只显示所提供文件的绝对路径,但前提是该文件存在。

#! /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 "a a"
/home/user/a a
$ fullpath ~/a\ a
/home/user/a a
$ fullpath A
A: No such file or directory.