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

其他回答

我用单线

(cd ${FILENAME%/*}; pwd)

但是,这只能在$FILENAME有一个实际存在的任何类型的前导路径(相对或绝对)时使用。如果根本没有前导路径,那么答案就是$PWD。如果前导路径不存在,则答案可能是不确定的,否则,如果路径是绝对路径,则答案只是${FILENAME%/*}。

把这些放在一起,我建议使用下面的函数

function abspath() {
  # argument 1: file pathname (relative or absolute)
  # returns: file pathname (absolute)
  if [ "$1" == "${1##*/}" ]; then # no path at all
    echo "$PWD"
  elif [ "${1:0:1}" == "/" -a "${1/../}" == "$1" ]; then # strictly absolute path
    echo "${1%/*}"
  else # relative path (may fail if a needed folder is non-existent)
    echo "$(cd ${1%/*}; pwd)"
  fi
}

还要注意,这只适用于bash和兼容的shell。我不相信替换在简单的shell sh中起作用。

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

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

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

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

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

试试readlink,它将解析符号链接:

readlink -e /foo/bar/baz

这里有一个只使用zsh的函数,我喜欢它的紧凑性。它使用了“A”扩展修饰符—参见zshexpn(1)。

realpath() { for f in "$@"; do echo ${f}(:A); done }