451 Stimmen

Wie kann ich das Verhalten von GNU's readlink -f auf einem Mac erhalten?

Unter Linux wird die readlink Dienstprogramm akzeptiert eine Option -f die zusätzlichen Links folgt. Dies scheint auf Mac- und möglicherweise BSD-basierten Systemen nicht zu funktionieren. Was wäre die Entsprechung?

Hier sind einige Debug-Informationen:

$ which readlink; readlink -f
/usr/bin/readlink
readlink: illegal option -f
usage: readlink [-n] [file ...]

1 Stimmen

Etwas spät, aber in Ihrer Frage fehlt ein Hinweis auf die von Ihnen verwendete Shell. Dies ist wichtig, denn readlink kann ein eingebauter oder ein externer Befehl sein.

1 Stimmen

Das würde vielleicht den Unterschied erklären. Ich bin mir aber ziemlich sicher, dass ich bei beiden Gelegenheiten die Bash verwendet habe.

3 Stimmen

Warum ist diese Option auf Macs verboten?

6voto

G. Cito Punkte 6004

FreeBSD y OSX haben eine Version von stat abgeleitet von NetBSD.

Sie können die Ausgabe mit Formatschaltern anpassen (siehe die Handbuchseiten unter den obigen Links).

%  cd  /service
%  ls -tal 
drwxr-xr-x 22 root wheel 27 Aug 25 10:41 ..
drwx------  3 root wheel  8 Jun 30 13:59 .s6-svscan
drwxr-xr-x  3 root wheel  5 Jun 30 13:34 .
lrwxr-xr-x  1 root wheel 30 Dec 13 2013 clockspeed-adjust -> /var/service/clockspeed-adjust
lrwxr-xr-x  1 root wheel 29 Dec 13 2013 clockspeed-speed -> /var/service/clockspeed-speed
% stat -f%R  clockspeed-adjust
/var/service/clockspeed-adjust
% stat -f%Y  clockspeed-adjust
/var/service/clockspeed-adjust

Einige OS X-Versionen von stat kann es an den -f%R Option für Formate. In diesem Fall -stat -f%Y kann ausreichen. Die -f%Y Option zeigt das Ziel eines Symlinks an, während -f%R zeigt den absoluten Pfadnamen an, der der Datei entspricht.

EDITAR:

Wenn Sie in der Lage sind, Perl zu benutzen (Darwin/OS X wird mit aktuellen Versionen von perl ) dann:

perl -MCwd=abs_path -le 'print abs_path readlink(shift);' linkedfile.txt

wird funktionieren.

2 Stimmen

Dies gilt für FreeBSD 10, aber nicht für OS X 10.9.

0 Stimmen

Ein guter Fang. Die stat Handbuchseite zitiert wird, ist für OS/X 10.9. Die R Option zu -f% fehlt. Möglicherweise stat -f%Y ergibt das gewünschte Ergebnis. Ich werde die Antwort anpassen. Beachten Sie, dass die stat wurde in FreeBSD in Version 4.10 und in NetBSD in Version 1.6 eingeführt.

0 Stimmen

Der Perl-Befehl funktioniert unter 10.15 nicht korrekt. Geben Sie ihm eine Datei im aktuellen Verzeichnis und er gibt das aktuelle Verzeichnis (ohne die Datei) aus.

6voto

AveryFreeman Punkte 784

Der einfachste Weg, dieses Problem zu lösen und die Funktionalität von readlink auf einem Mac mit installiertem Homebrew oder FreeBSD zu aktivieren, ist die Installation des Pakets 'coreutils'. Dies kann auch auf bestimmten Linux-Distributionen und anderen POSIX-Betriebssystemen notwendig sein.

Unter FreeBSD 11 zum Beispiel habe ich die Installation durch den Aufruf von:

# pkg install coreutils

Unter MacOS mit Homebrew würde der Befehl lauten:

$ brew install coreutils

Ich weiß nicht, warum die anderen Antworten so kompliziert sind, das ist alles, was ich weiß. Die Dateien befinden sich nicht an einem anderen Ort, sie sind nur noch nicht installiert.

8 Stimmen

brew install coreutils --with-default-names um genauer zu sein. Sonst endet das Ganze mit "greadlink"...

0 Stimmen

Ich kann keinen Unterschied zu den Antworten von 2010 erkennen. stackoverflow.com/a/4031502/695671 und 2012 stackoverflow.com/a/9918368/695671 Die Frage lautet eigentlich "... auf Mac- und möglicherweise BSD-basierten Systemen. Was wäre die Entsprechung?" Ich glaube nicht, dass dies eine sehr gute Antwort auf diese Frage ist. Dafür gibt es viele Gründe, aber möglicherweise zielen Sie auf Mac OS-Systeme ab, auf denen Sie nichts installieren können. pwd -P ist ziemlich einfach, aber sie verschwindet unter vielen anderen Antworten, auch unter wiederholten, daher die Ablehnung.

0 Stimmen

FreeBSD hatte readlink -f seit fünf Jahre bevor Sie diese Antwort geschrieben haben . Ich würde also vorschlagen, diesen Teil zu entfernen. Ansonsten: gute Vorschläge.

5voto

masta Punkte 109

Hier ist eine portable Shell-Funktion, die in ANY Bourne vergleichbare Shell. Sie löst die relative Pfadinterpunktion ".. oder ." auf und dereferenziert symbolische Links.

Wenn Sie aus irgendeinem Grund keinen realpath(1)-Befehl oder readlink(1)-Befehl haben, kann dies als Alias verwendet werden.

which realpath || alias realpath='real_path'

Viel Spaß!

real_path () {
  OIFS=$IFS
  IFS='/'
  for I in $1
  do
    # Resolve relative path punctuation.
    if [ "$I" = "." ] || [ -z "$I" ]
      then continue
    elif [ "$I" = ".." ]
      then FOO="${FOO%%/${FOO##*/}}"
           continue
      else FOO="${FOO}/${I}"
    fi

    ## Resolve symbolic links
    if [ -h "$FOO" ]
    then
    IFS=$OIFS
    set `ls -l "$FOO"`
    while shift ;
    do
      if [ "$1" = "->" ]
        then FOO=$2
             shift $#
             break
      fi
    done
    IFS='/'
    fi
  done
  IFS=$OIFS
  echo "$FOO"
}

Außerdem, nur für den Fall, dass es jemanden interessiert, hier ist, wie man basename und dirname in 100% reinem Shell-Code implementiert:

## http://www.opengroup.org/onlinepubs/000095399/functions/dirname.html
# the dir name excludes the least portion behind the last slash.
dir_name () {
  echo "${1%/*}"
}

## http://www.opengroup.org/onlinepubs/000095399/functions/basename.html
# the base name excludes the greatest portion in front of the last slash.
base_name () {
  echo "${1##*/}"
}

Sie können eine aktualisierte Version dieses Shell-Codes auf meiner Google-Seite finden: http://sites.google.com/site/jdisnard/realpath

EDIT: Dieser Code steht unter den Bedingungen der 2-Klausel-Lizenz (im Stil von freeBSD). Eine Kopie der Lizenz finden Sie, wenn Sie dem obigen Hyperlink zu meiner Website folgen.

0 Stimmen

Der real_path gibt unter Mac OS X Lion in der Bash-Shell /filename statt /path/to/filename zurück.

0 Stimmen

@Barry Das Gleiche passiert unter OSX Snow Leopard. Schlimmer noch, aufeinanderfolgende Aufrufe von real_path() verketten die Ausgabe!

0 Stimmen

@Dominique: nicht überraschend, da das Innere der Funktion nicht in einer eigenen Subshell ausgeführt wird ... in der Tat hässlich und anfällig.

4voto

levinit Punkte 197

Echo $(cd $(Verzeichnisname Datei1) ; pwd -P)

2 Stimmen

Dies sollte die akzeptierte Antwort sein, da sie das Problem sofort löst, ohne dass komplizierte Funktionen geschrieben oder zusätzliche Abhängigkeiten installiert werden müssen. man readlink unter Linux: -f canonicalize by following every symlink... , man pwd auf macOS: -P Display the physical current workign directory (all symbolic links resolved)

1 Stimmen

Die einzige tragbare Antwort, die nicht das Schreiben einer verrückten Menge zusätzlichen Codes erfordert.

0 Stimmen

Erzeugt eine falsche Ausgabe, wenn file1 ist ein Symlink.

2voto

estani Punkte 20703

Es gibt schon viele Antworten, aber keine hat bei mir funktioniert... Also, das ist, was ich jetzt benutze.

readlink_f() {
  local target="$1"
  [ -f "$target" ] || return 1 #no nofile

  while [ -L "$target" ]; do
    target="$(readlink "$target")" 
  done
  echo "$(cd "$(dirname "$target")"; pwd -P)/$target"
}

1 Stimmen

Dies funktioniert nicht, wenn die $target ein Pfad ist, funktioniert es nur, wenn es sich um eine Datei handelt.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X