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

其他回答

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

不需要任何工具(只需要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命令。它只显示所提供文件的绝对路径,但前提是该文件存在。

我用单线

(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中起作用。

我已经在我的系统上放置了以下脚本&当我想快速获取当前目录下文件的完整路径时,我将其称为bash别名:

#!/bin/bash
/usr/bin/find "$PWD" -maxdepth 1 -mindepth 1 -name "$1"

我不知道为什么,但是,在OS X上,当被脚本“$PWD”调用时,扩展到绝对路径。当在命令行上调用find命令时,它不会执行。但这是我想要的…享受。

#! /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.