如何從 OS X 檢索任意檔案的絕對路徑

如何從 OS X 檢索任意檔案的絕對路徑

我正在尋找一個可以在 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

與上例中最後一次調用“abspath”一樣,我希望它不會自動解析符號鏈接,但我在這裡不會太挑剔。

答案1

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; }

例子:

abspath / => /

abspath /.DS_Store => /.DS_Store

abspath ~ => /Users/mschrag

cd /tmp; abspath . => /tmp

cd /; abspath .DS_Store => /.DS_Store

答案2

我認為沒有內建命令可以執行此操作。傑西威爾遜為此寫了一個 bash 腳本:

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

/但是,它對於直接位於 下方的路徑(例如/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)

另存為/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

如果你想要符號連結解析,請print像這樣更改行:

    print os.path.realpath(os.path.abspath(arg))

得到這個:

Servus08:~ danielbeck$ abspath . /tmp Documents
/Users/danielbeck
/private/tmp
/Users/danielbeck/Documents

答案3

一種選擇是僅安裝 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
$ 

這不會解析符號鏈接,並且兩者都不起作用/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/

dirs -l執行波形符擴充。dirs +0如果堆疊中還有其他目錄,則僅列印最頂層的目錄。

答案4

如果你為 perl 安裝了 File::Spec 模組,你可以這樣做:

perl -MFile::Spec -e 'print File::Spec->rel2abs("../however/complex/../you/want/to.get"), "\n"'

相關內容