So rufen Sie den absoluten Pfad einer beliebigen Datei aus OS X ab

So rufen Sie den absoluten Pfad einer beliebigen Datei aus OS X ab

Ich suche nach einem einfachen Befehl, der in Bash verwendet werden kann, um den absoluten und kanonisierten Pfad zu einer Datei unter OS X zu finden (ähnlich wie „readlink -f“ unter Linux).

Die folgende Beispiel-Bash-Sitzung beschreibt ein [fiktives] Dienstprogramm namens „abspath“, das das gewünschte Verhalten aufweist:

$ 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

Wie beim letzten Aufruf von „abspath“ im obigen Beispiel wäre es mir lieber, wenn symbolische Links nicht automatisch aufgelöst würden, aber ich will hier nicht zu pingelig sein.

Antwort1

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

Beispiele:

abspath / => /

abspath /.DS_Store => /.DS_Store

abspath ~ => /Users/mschrag

cd /tmp; abspath . => /tmp

cd /; abspath .DS_Store => /.DS_Store

Antwort2

Ich glaube nicht, dass es einen integrierten Befehl gibt, der dies tut.Jesse Wilsonhabe dazu ein Bash-Skript geschrieben:

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

Es funktioniert jedoch nicht gut für Pfade direkt darunter /, wie /etc(Drucken //etc), sowie .und ..(Drucken /cwd/.in beiden Fällen). Ich habe versucht, es zu ändern, aber mein unzureichendes Bash-Fu hat mich im Stich gelassen.

Hier ist mein Vorschlag:

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

for arg in sys.argv[1:]:
    print os.path.abspath(arg)

Speichern unter /usr/bin/abspathoder so ähnlich und ausführbar machen. Beispielausgabe:

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

Wenn duTunWenn Sie eine symbolische Linkauflösung wünschen, ändern Sie die printZeile wie folgt:

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

um dies zu erhalten:

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

Antwort3

Eine Möglichkeit wäre, einfach coreutils zu installieren und zu verwenden greadlink -f. Es löst symbolische Links auf und funktioniert mit /Foo/oder ~/foo.txt, wenn sie nicht vorhanden sind, aber nicht mit , /Foo/foo.txtwenn /Foo/nicht vorhanden ist.

$ 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
$ 

Dies löst keine symbolischen Links auf und funktioniert mit /Foo/foo.txtbeiden nicht.

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 -lFührt eine Tilde-Erweiterung durch. dirs +0Druckt nur das oberste Verzeichnis, wenn sich andere Verzeichnisse im Stapel befinden.

Antwort4

Wenn Sie das Modul File::Spec für Perl installiert haben, können Sie einfach Folgendes tun:

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

verwandte Informationen