如何从 OS X 检索任意文件的绝对路径

Mic*_*ner 17 bash shell osx-snow-leopard macos

我正在寻找一个简单的命令,可以在 Bash 中使用它来查找 OS X 上文件的绝对和规范化路径(类似于 Linux 下的“readlink -f”)。

以下示例 bash 会话描述了一个名为“abspath”的 [虚构] 实用程序,它展示了所需的行为:

$ pwd
/Users/guyfleegman

$ ls -lR
drwxr-xr-x  4 guyfleegman  crew  136 Oct 30 02:09 foo

./foo:
-rw-r--r--  1 guyfleegman  crew  0 Oct 30 02:07 bar.txt
lrwxr-xr-x  1 guyfleegman  crew  7 Oct 30 02:09 baz.txt -> bar.txt


$ abspath .
/Users/guyfleegman

$ abspath foo
/Users/guyfleegman/foo

$ abspath ./foo/bar.txt
/Users/guyfleegman/foo/bar.txt

$ abspath foo/baz.txt
/Users/guyfleegman/foo/baz.txt
Run Code Online (Sandbox Code Playgroud)

与上面示例中最后一次调用“abspath”一样,我希望它不会自动解析符号链接,但我不会在这里太挑剔。

小智 15

function abspath() { pushd . > /dev/null; if [ -d "$1" ]; then cd "$1"; dirs -l +0; else cd "`dirname \"$1\"`"; cur_dir=`dirs -l +0`; if [ "$cur_dir" == "/" ]; then echo "$cur_dir`basename \"$1\"`"; else echo "$cur_dir/`basename \"$1\"`"; fi; fi; popd > /dev/null; }
Run Code Online (Sandbox Code Playgroud)

例子:

abspath / => /

abspath /.DS_Store => /.DS_Store

abspath ~ => /Users/mschrag

cd /tmp; abspath . => /tmp

cd /; abspath .DS_Store => /.DS_Store
Run Code Online (Sandbox Code Playgroud)


Dan*_*eck 12

我不认为有一个内置命令可以做到这一点。Jesse Wilson为此编写了一个 bash 脚本:

#!/bin/bash
cd -P -- "$(dirname -- "$1")" &&
printf '%s\n' "$(pwd -P)/$(basename -- "$1")"
Run Code Online (Sandbox Code Playgroud)

但是,它不适用于 正下方的路径/,例如/etc(printing //etc) 以及.and ..(/cwd/.在这两种情况下都打印)。我尝试修改它,但我的 bash-fu 不足让我失望。

这是我的建议:

#!/usr/bin/env python
import os.path
import sys

for arg in sys.argv[1:]:
    print os.path.abspath(arg)
Run Code Online (Sandbox Code Playgroud)

另存为/usr/bin/abspath或类似的东西并使其可执行。示例输出:

Servus08:~ danielbeck$ abspath .
/Users/danielbeck
Servus08:~ danielbeck$ abspath /tmp
/tmp
Servus08:~ danielbeck$ abspath Documents
/Users/danielbeck/Documents
Servus08:~ danielbeck$ abspath . /tmp Documents
/Users/danielbeck
/tmp
/Users/danielbeck/Documents
Run Code Online (Sandbox Code Playgroud)

如果您确实需要符号链接解析,请print像这样更改行:

    print os.path.realpath(os.path.abspath(arg))
Run Code Online (Sandbox Code Playgroud)

得到这个:

Servus08:~ danielbeck$ abspath . /tmp Documents
/Users/danielbeck
/private/tmp
/Users/danielbeck/Documents
Run Code Online (Sandbox Code Playgroud)

  • @迈克尔您要么在带有 GNU readlink 的系统上,要么在 OS X 上——对吗?OS X 具有开箱即用的 Python。理论上它是一个新的依赖项,实际上不是。不管怎样,我能给你的就只有这些了。 (2认同)
  • @Michael,为什么 Python 不是 OS X 上的好选择?它甚至附带了实际上是 Python 脚本的命令,例如 `file /usr/bin/xattr` (2认同)

Lri*_*Lri 8

一种选择是只安装 coreutils 并使用greadlink -f. 它解决符号链接,并将其与工作/Foo/或者~/foo.txt如果他们不存在,但不是/Foo/foo.txt如果/Foo/不存在。

$ brew install coreutils
$ greadlink -f /etc
/private/etc
$ greadlink -f ~/Documents/
/Users/lauri/Documents
$ greadlink -f ..
/Users
$ greadlink -f //etc/..////
/private
$ greadlink -f /Foo
/Foo
$ greadlink -f /Foo/foo.txt
$ 
Run Code Online (Sandbox Code Playgroud)

这不能解析符号链接,也不能与它们一起/Foo/foo.txt使用。

abspath() {
  if [ -d "$1" ]; then
    ( cd "$1"; dirs -l +0 )
  else
    ( cd "$(dirname "$1")"; d=$(dirs -l +0); echo "${d%/}/${1##*/}" )
  fi
}

abspath /etc # /etc
abspath ~/Foo/foo.txt # doesn't work
abspath ~/Foo # works
abspath .
abspath ./
abspath ../
abspath ..
abspath /
abspath ~
abspath ~/
abspath ~/Documents
abspath /\"\ \'
abspath /etc/../etc/
abspath /private//etc/
abspath /private//
abspath //private # //private
abspath ./aa.txt
abspath aa.tar.gz
abspath .aa.txt
abspath /.DS_Store
abspath ~/Documents/Books/
Run Code Online (Sandbox Code Playgroud)

dirs -l执行波浪号扩展。dirs +0如果堆栈中还有其他目录,则仅打印最顶层的目录。