关于shell:bash / fish命令打印文件的绝对路径

bash/fish command to print absolute path to a file

问题:是否有一个简单的sh/bash/zsh/fish/…命令打印我输入的任何文件的绝对路径?

使用案例:我在/a/b目录中,我想打印命令行上文件c的完整路径,这样我就可以轻松地将其粘贴到另一个程序:/a/b/c中。简单,但一个小程序来做这可能会节省我5秒左右,当涉及到处理长路径时,这最终会增加。所以我很惊讶我找不到一个标准的实用程序来做这个-真的没有吗?

下面是一个示例实现abspath.py:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
#!/usr/bin/python
# Author: Diggory Hardy <[email protected]>
# 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试试。

1
2
$ realpath example.txt
/home/username/example.txt


这将尝试解决readlink符号链接:

1
readlink -e /foo/bar/baz


1
2
#! /bin/sh
echo"$(cd"$(dirname"$1")"; pwd -P)/$(basename"$1")"


忘记系统上可能安装或不安装的readlinkrealpath

在上面对Dogbane的答案进行扩展,它表示为一个函数:

1
2
3
4
5
#!/bin/bash
get_abs_filename() {
  # $1 : relative filename
  echo"$(cd"$(dirname"$1")" && pwd)/$(basename"$1")"
}

然后您可以这样使用它:

1
myabsfile=$(get_abs_filename"../../foo/bar/file.txt")

它如何工作,为什么工作?

该解决方案利用了这样一个事实:bash内置的pwd命令在不带参数调用时将打印当前目录的绝对路径。

为什么我喜欢这个解决方案?

它是可移植的,不需要readlinkrealpath,这通常不存在于给定的linux/unix发行版的默认安装中。

如果dir不存在怎么办?

如上所述,如果给定的目录路径不存在,函数将失败并在stderr上打印。这可能不是你想要的。您可以展开函数来处理这种情况:

1
2
3
4
5
6
7
#!/bin/bash
get_abs_filename() {
  # $1 : relative filename
  if [ -d"$(dirname"$1")" ]; then
    echo"$(cd"$(dirname"$1")" && pwd)/$(basename"$1")"
  fi
}

现在,如果父目录不存在,它将返回一个空字符串。

如何处理输入中的后缀".."或"."?

在这种情况下,它确实给出了一条绝对路径,但不是最小路径。它看起来像:

1
/Users/bob/Documents/..

如果要解析"..",需要使脚本如下:

1
2
3
4
5
6
7
8
9
10
11
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
}


1
2
$ readlink -m FILE
/path/to/FILE

这是一readlink -e FILErealpath比,因为它的工作,如果文件是不是存在。


绝对路径转换器外壳函数的相对路径

  • 不需要公用设施(仅cdpwd)
  • 适用于目录和文件
  • 处理...
  • 处理目录或文件名中的空格
  • 要求文件或目录存在
  • 如果给定路径中不存在任何内容,则返回Nothing
  • 作为输入处理绝对路径(基本上通过它们)

代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
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
}

Sample:

1
2
3
4
5
6
7
8
# 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

1
2
find $PWD -name ex*
find $PWD -name example.log

下面列出的所有文件在当前目录的名称或与之匹配的模式。它可以简化,如果你只会得到一些结果(例如,目录树的底部附近,几只含文件)

1
find $PWD

我使用这个在线的Solaris 10,这是不是已经提到的其他工具。


如果你不有一个比你可以或公用事业readlink realpath使用功能后,作品在bash和zsh(不确定关于the Rest)。

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

本厂是nonexistent文件(也做os.path.abspath的Python函数。

不幸的是abspath ./../somefile不是摆脱该点。


这是只有在zsh是它的功能我喜欢它们。它使用了"国有企业"zshexpn展开修改器(1)。

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


这样的事情有一个大致的absolute path到文件(这意味着语句可以有一个以上的在一般的定,因此使用的是不适当的文章)。这是一absolute path启动任何路径从根"/"和designates ambiguity没有独立的文件的工作目录(见例如维基百科)。。。。。。。。。。。。。。

这是一relative path路径是从另一个是interpreted启动目录。它可能是,如果它的工作目录是由人的relative pathmanipulated应用(虽然不一定)。当它是一个符号链接在目录中,它是相对于一般的目的是目录(虽然可能有其他用户使用的记忆中)。

因此一个绝对路径是只是相对于根目录的路径。

路径(绝对或相对)可能或可能不包含的符号链接。如果它不,它是有点impervious也对链接结构变化的必然要求,但这不是一desirable或盈亏平衡点。一些人(或canonical file name或呼叫canonical pathresolved path)在其中的所有符号链接的一absolute path已分辨,即已被替换由whetever路径链接到他们。《命令与readlinkrealpath正则路径都看,但只有一个是有一realpath期权获得了绝对路径的符号链接(没有bothering随着一些其他选项,以获得不同的一种绝对或相对路径,一些目录)。

这将调用的话:

  • 符号链接也可以只可分辨的,如果他们是应该创建一个链接到已经是显然的,永远不结婚。《命令与readlinkrealpath到客户那一选项。
  • 该指南的路径后,可以成为符号链接路径,这意味canonical不再是。因此在时间(或环境)的概念是相关的。
  • 即使在理想的案例,当所有的符号链接可以分辨。还可以有一个以上的canonical path是到文件,双原因:
    • 该分区上的文件可能有一个含(山ro)同时在线的几个点。
    • 有可能是该文件的硬链接的文件存在的意义,本质上,在几个不同的目录。
  • 因此,即使与多canonical path有限制性的定义,可以对几种典型路径下的文件。这也意味canonical不少,因为它是一个有点比赛通常意味着其唯一性的概念。

    这扩大了简短的讨论的话题在一到另一个类似的问题的答案:在检索了绝对路径的相对的bash

    我的结论是,realpath是更好的设计和更大的比readlink灵活。这是唯一的使用不受realpathreadlink呼叫是没有返回值的选择对符号链接。


    dogbane回答了以下问题:

    1
    2
    #! /bin/sh
    echo"$(cd"$(dirname"$1")"; pwd)/$(basename"$1")"

    说明:

  • 这个脚本得到相对路径作为参数"$1"
  • 然后我们得到该路径的dirname部分(您可以将dir或file传递给这个脚本):dirname"$1"
  • 然后我们进入这个相对目录,通过运行pwdshell命令得到它的绝对路径。
  • 之后,我们将basename附加到绝对路径:$(basename"$1")
  • 作为最后一步,我们决定

  • 这不是问题的答案,但对于编写脚本的人来说:

    1
    echo `cd"$1" 2>/dev/null&&pwd||(cd"$(dirname"$1")";pwd|sed"s|/*\$|/${1##*/}|")`

    它处理/。等正确。我也在OSX上工作


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

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

    我不知道为什么,但在OSX上,当脚本"$pwd"调用时,它会扩展到绝对路径。当在命令行上调用find命令时,它不会调用。但它会执行我想要的操作…享受。


    对于目录dirname../触发并返回./

    可以修改nolan6000的功能来修复:

    1
    2
    3
    4
    5
    6
    get_abs_filename() {
      # $1 : relative filename
      if [ -d"${1%/*}" ]; then
        echo"$(cd ${1%/*}; pwd)/${1##*/}"
      fi
    }


    1
    2
    3
    4
    #! /bin/bash

    file="$@"
    realpath"$file" 2>/dev/null || eval realpath $(echo $file | sed 's/ /\\ /g')

    这弥补了realpath的缺点,将其存储在shell脚本fullpath中。您现在可以拨打:

    1
    2
    3
    4
    5
    6
    7
    $ 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.


    在Ruby中获取绝对路径的另一种方法是:

    realpath() {ruby -e"require 'Pathname'; puts Pathname.new('$1').realpath.to_s";}

    不使用参数(当前文件夹)和相对和绝对文件或文件夹路径作为参数。


    嘿,伙计们,我知道这是一条老线索,但我只是把它贴出来,以供其他像我一样访问过这个网站的人参考。如果我正确理解了这个问题,我认为是由locate $filename指挥的。它显示所提供文件的绝对路径,但仅当它存在时才显示。