Befehl bash / fish, um den absoluten Pfad zu einer Datei zu drucken


448

Frage: Gibt es einen einfachen Befehl sh / bash / zsh / fish / ..., um den absoluten Pfad der Datei zu drucken, die ich füttere?

Anwendungsfall: Ich bin im Verzeichnis /a/bund möchte den vollständigen Pfad zur Datei cin der Befehlszeile drucken , damit ich ihn einfach in ein anderes Programm einfügen kann : /a/b/c. Ein einfaches, aber ein kleines Programm, um dies zu tun, könnte mir wahrscheinlich 5 oder so Sekunden sparen, wenn es darum geht, lange Pfade zu bewältigen, was sich letztendlich summiert. Es überrascht mich also, dass ich kein Standarddienstprogramm dafür finden kann - gibt es wirklich keines?

Hier ist eine Beispielimplementierung, abspath.py:

#!/usr/bin/python
# Author: Diggory Hardy <diggory.hardy@gmail.com>
# 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)

Ich würde argumentieren, dass die Antwort von @ DennisWilliamson (mit der Option -m) überlegen ist, um (normalerweise) portabler zu sein und mit Dateien zu arbeiten, die nicht existieren.
TTT

Oder Flimms Antwort; beides sind gute lösungen. Bannier's beantwortet jedoch meine ursprüngliche Frage am besten.
Dhardy

3
OSX-Benutzer: siehe diese Antwort
Ian

Antworten:


560

Versuchen Sie es realpath.

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

133
+1, sehr schönes Programm. Beachten Sie jedoch, dass es sich um einen externen Befehl handelt (keine integrierte Shell) und möglicherweise nicht standardmäßig in jedem System vorhanden ist, dh Sie müssen ihn möglicherweise installieren. In Debian befindet es sich in einem separaten Paket mit demselben Namen.
Roman Cheplyaka


1
@Flimm: Es gibt Ihnen immer noch einen gültigen Pfad, wenn ein relativer Pfad angegeben ist. Wenn Sie mehr über die Existenz von Dateien erfahren möchten, verwenden Sie ein anderes Tool wie z. B. test.
Benjamin Bannier

14
@Dalin: Versuchen Sie Coreutils zu installieren. Die Binärdatei heißt grealpath.
Toni Penya-Alba

5
Dieses Tool wurde in GNU Coreutils 8.15 (2012) eingeführt, ist also ziemlich neu.
März

317

Versuchen Sie, readlinkwelche symbolischen Links aufgelöst werden:

readlink -e /foo/bar/baz

50
Ich würde lieber '-f' anstelle von '-e' verwenden, damit wir den absoluten Pfad einer nicht existierenden Datei sehen können.
hluk

5
Das sieht für mich am einfachsten aus und ist gleichzeitig tragbar. readlink ist der Port der gnu coreutils, daher wird es auf fast jeder Linux-Distribution installiert, mit Ausnahme einiger eingebetteter.
Catphive

14
Es scheint mir, dass dies -mdie beste Option ist.
Matt Joiner

1
@Dalin: /usr/bin/readlinkauf Mavericks. Oder meinten Sie, dass diese Optionen unter OS X nicht gefunden werden? Es scheint eine verkümmerte BSD-Version zu sein ...: p
iconoclast

14
@iconoclast Diese Optionen sind unter OSX nicht verfügbar und laut BSD- readlinkManpage : only the target of the symbolic link is printed. If the given argument is not a symbolic link, readlink will print nothing and exit with an error, daher funktioniert Readlink für diesen Zweck unter OSX nicht
SnoringFrog

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

8
Vergiss nicht, alles zu zitieren. Wenn Sie nicht verstehen, warum, versuchen Sie Ihr Programm in einer Datei a b(zwei Leerzeichen zwischen a und b, SO isst eines davon).
Roman Cheplyaka

1
Versuchen Sie dies auch auf "/", es wird zu "///"
George

34
Die einzige POSIX-Lösung, bei der Sie keine ausführbare Datei schreiben und kompilieren müssen, da Readlink und Realpath nicht POSIX sind
Ciro Santilli 29 冠状 病 六四 事件 法轮功

25
Ich habe function realpath { echo $(cd $(dirname $1); pwd)/$(basename $1); }mir unter realpathOS X einen Befehl (derzeit akzeptierte Antwort) gemacht. Danke!
James Bedford

1
Ich habe diese Methode verwendet, um Protokolldateinamen für Skripte zu definieren:LOG=$(echo $(cd $(dirname $0); pwd)/$(basename $0 .sh).log)
DrStrangepork

83

Vergessen Sie readlinkund realpathdie auf Ihrem System sein oder kann nicht installiert werden.

Die Antwort von dogbane oben wird hier als Funktion ausgedrückt:

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

Sie können es dann folgendermaßen verwenden:

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

Wie und warum funktioniert es?

Die Lösung nutzt die Tatsache aus, dass der integrierte pwdBefehl Bash den absoluten Pfad des aktuellen Verzeichnisses druckt, wenn er ohne Argumente aufgerufen wird.

Warum mag ich diese Lösung?

Es ist portabel und erfordert weder eines readlinknoch das, realpathwas bei einer Standardinstallation einer bestimmten Linux / Unix-Distribution häufig nicht vorhanden ist.

Was ist, wenn dir nicht existiert?

Wie oben angegeben, schlägt die Funktion fehl und wird auf stderr gedruckt, wenn der angegebene Verzeichnispfad nicht vorhanden ist. Dies ist möglicherweise nicht das, was Sie wollen. Sie können die Funktion erweitern, um diese Situation zu behandeln:

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

Jetzt wird eine leere Zeichenfolge zurückgegeben, wenn eines der übergeordneten Verzeichnisse nicht vorhanden ist.

Wie gehst du mit '..' oder '.' in Eingabe?

Nun, es gibt in diesem Fall einen absoluten Pfad, aber keinen minimalen. Es wird so aussehen:

/Users/bob/Documents/..

Wenn Sie das '..' auflösen möchten, müssen Sie das Skript wie folgt erstellen:

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
}

Gute Funktion, aber anscheinend haben Sie die Frage nicht verstanden. Ich wollte etwas für den interaktiven Gebrauch, keine Skripte.
Dhardy

3
Ich möchte hinzufügen , dass realpathaus coreutils Paket kommt, die auch enthält Tools wie who, touchoder cat. Es handelt sich um eine ziemlich standardmäßige Reihe von GNU-Tools, sodass Sie ziemlich sicher sein können, dass diese auf fast jedem Linux-basierten Computer installiert ist. Sie haben jedoch Recht: Es gibt zwei Probleme: i) Sie werden sie wahrscheinlich bei der Standardinstallation auf vermissen Nicht-GNU-Unix-Systeme (wie OpenBSD) ii) Dieses Tool wurde in Version 8.15 eingeführt (es ist also ab 2012 ziemlich neu), sodass Sie es auf langfristig stabilen Systemen (wie RHEL 6) vermissen werden.
März

1
Nun, es scheint zumindest, dass Continuum Analytics (Hersteller der Anaconda Python-Distribution ) diese Antwort gefallen hat. Es ist (mit einer Referenz, die hierher zurückführt) in ihrem "Aktivierungs" -Skript implementiert, das zum Aktivieren von virtuellen Umgebungen verwendet wird, die vom conda-Tool erstellt wurden. Also ... gut!
wjv

1
Dies funktioniert nur für Verzeichnisse (da es sonst nichts gibt) und kann mit ".." und "." Nicht umgehen. Siehe meine Antwort, die alles behandeln sollte: stackoverflow.com/a/23002317/2709
Alexander Klimetschek

3
@marbu realpath ist unter Ubuntu 14.04 oder Debian Wheezy nicht vorhanden. Es mag im Laufe der Zeit etwas Standard werden, aber es ist sicherlich nicht jetzt. Beachten Sie auch, dass das OP nichts über Linux oder GNU gesagt hat. Bash ist weit verbreitet.
mc0e

76
$ readlink -m FILE
/path/to/FILE

Dies ist besser als readlink -e FILEoder realpath, da es auch dann funktioniert, wenn die Datei nicht vorhanden ist.


Nett. Dies funktioniert auch für Dateien / Verzeichnisse, die vorhanden sind, aber keine Symlinks sind.
quietmint

Ich habe einen Readlink unter OS X 10.9 (Mavericks), daher ist dies definitiv die beste Antwort hier.
Kenneth Hoste

6
@KennethHoste: Die -mOption ist bei Mavericks nicht verfügbar.
Bilderstürmer

2
Auf jeden Fall ist es nicht auf einer DEFAULT OSX-Installation.
Fran Marzoa

funktioniert unter Linux (CentOS) Danke, weil Realpath dafür nicht existierte
Jimh

65

Dieser relative Pfad zur absoluten Pfadkonverter- Shell-Funktion

  • erfordert keine Dienstprogramme (nur cdund pwd)
  • funktioniert für Verzeichnisse und Dateien
  • Griffe ..und.
  • behandelt Leerzeichen in Verzeichnis oder Dateinamen
  • erfordert, dass eine Datei oder ein Verzeichnis vorhanden ist
  • gibt nichts zurück, wenn am angegebenen Pfad nichts vorhanden ist
  • behandelt absolute Pfade als Eingabe (durchläuft sie im Wesentlichen)

Code:

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
}

Stichprobe:

# 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

Hinweis: Dies basiert auf den Antworten von nolan6000 und bsingh , behebt jedoch den Dateifall .

Ich verstehe auch, dass die ursprüngliche Frage ein vorhandenes Befehlszeilenprogramm betraf. Aber da dies DIE Frage zum Stackoverflow zu sein scheint, einschließlich Shell-Skripten, die minimale Abhängigkeiten aufweisen möchten, habe ich diese Skriptlösung hier eingefügt, damit ich sie später finden kann :)


Vielen Dank. Das ist, was ich unter OSX mache
Greg

Dies funktioniert nicht für Verzeichnisse mit Leerzeichen, dh: $ abspath 'a b c/file.txt'Das Argument zu cdwird nicht in Anführungszeichen gesetzt. Um dies zu überwinden, zitieren Sie anstelle des gesamten Arguments echo(gibt es einen Grund für diese Anführungszeichen?) Nur die Pfadargumente. Dh ersetzen echo "$(cd ${1%/*}; pwd)/${1##*/}"durch echo $(cd "${1%/*}"; pwd)/${1##*/}.
George

@george Danke für die Notiz, ich habe es behoben.
Alexander Klimetschek

1
Ich habe Dutzende von halb gespannten Lösungen durchgesehen, und dies scheint definitiv die prägnanteste und genaueste Nur-Bash-Lösung zu sein. Sie könnten schlank es noch durch den Ersatz echo "$(cd "$1"; pwd)"mit (cd "$1"; pwd). Hier besteht keine Notwendigkeit für Echo.
Sechs

@Six True, aktualisiert. Die geschweiften Klammern ( ... )werden weiterhin benötigt, so dass cddies in einer Subshell geschieht, da wir das Arbeitsverzeichnis für keine Anrufer von ändern möchten abspath.
Alexander Klimetschek

24

Der findBefehl kann helfen

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

Listet alle Dateien im oder unter dem aktuellen Verzeichnis mit Namen auf, die dem Muster entsprechen. Sie können es vereinfachen, wenn Sie nur wenige Ergebnisse erhalten (z. B. Verzeichnis am unteren Rand des Baums mit wenigen Dateien)

find $PWD

Ich verwende dies unter Solaris 10, das nicht über die anderen genannten Dienstprogramme verfügt.


1
Ich habe diesen Kommentar beim ersten Lesen nicht gelesen. Der entscheidende Punkt hierbei ist, dass, wenn Sie dem Befehl find einen absoluten Pfad geben, die Ergebnisse in einem absoluten Pfad ausgegeben werden. Die Verwendung von $ PWD ist also der absolute Pfad, auf dem Sie sich befinden, sodass Sie die Ausgabe als absolut erhalten.
simbo1905

4
Wenn Sie sich darauf verlassen PWD, können Sie einfach verwenden $PWD/$filename.
Jonny

Dieser Ansatz kann durch die Verwendung von -maxdepth 1 verbessert werden. Vergessen Sie auch nicht das Zitieren - potenzielle Sicherheitsprobleme hier, je nachdem, wie Sie dies verwenden.
mc0e

1
@jonny: $ PWD / $ Dateiname schlägt fehl, wenn $ Dateiname bereits absolut ist.
mc0e

Dies schlägt fehl, wenn der Dateiname "./filename.txt" (mit führendem Punkt und Schrägstrich) angegeben wird.
Mark Stosberg

15

Wenn Sie keine Readlink- oder Realpath-Dienstprogramme haben, können Sie die folgende Funktion verwenden, die in bash und zsh funktioniert (über den Rest nicht sicher).

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

Dies funktioniert auch für nicht vorhandene Dateien (ebenso wie die Python-Funktion os.path.abspath).

Leider werden abspath ./../somefiledie Punkte nicht los.


1
Sieht für mich tragbar aus. Auf der anderen Seite wird beispielsweise ein Dateiname unterbrochen, der eine neue Zeile enthält.
Roman Cheplyaka

1
Um sich weiter zu verbessern, ersetzen Sie echo "$1"durch printf "%s\n" "$1"(dasselbe mit dem zweiten Echo). echokann Backslashes in seinen Argumenten interpretieren.
Roman Cheplyaka

Wieder hast du recht! Wirklich, das Verhalten des Echo-Befehls in zsh unterscheidet sich von bash.
hluk

1
Genau genommen ist das Verhalten von Echo unter POSIX undefiniert, wenn Argumente Backslashes enthalten. Es ist jedoch unter der XSI-Erweiterung definiert (Echo sollte die Escape-Sequenzen interpretieren). Aber sowohl bash als auch zsh sind so weit von der POSIX-Konformität entfernt ...
Roman Cheplyaka

Entschuldigung, aber ich verstehe den Punkt nicht. Ich habe bereits eine Antwort als Skript mit mehr Funktionen bereitgestellt, die nicht in einem Shell-Skript verwendet werden müssen.
Dhardy

10

Hier ist eine Nur-Zsh-Funktion, die ich wegen ihrer Kompaktheit mag. Es wird der Erweiterungsmodifikator 'A' verwendet - siehe zshexpn (1).

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

Wow das ist eine elegante Lösung !!
ShellFish

6

Es ist in der Regel nicht so etwas wie die absolute path in eine Datei (diese Aussage bedeutet , dass es im Allgemeinen mehr sein kann als ein, daher die Verwendung des bestimmten Artikels der nicht geeignet ist). An absolute pathist ein beliebiger Pfad, der vom Stammverzeichnis "/" ausgeht und eine Datei ohne Mehrdeutigkeit unabhängig vom Arbeitsverzeichnis bezeichnet (siehe z. B. Wikipedia ).

A relative pathist ein Pfad, der ausgehend von einem anderen Verzeichnis interpretiert werden soll. Es kann das Arbeitsverzeichnis sein, wenn es relative pathvon einer Anwendung manipuliert wird (wenn auch nicht unbedingt). Wenn es sich in einem symbolischen Link in einem Verzeichnis befindet, soll es im Allgemeinen relativ zu diesem Verzeichnis sein (obwohl der Benutzer möglicherweise andere Verwendungszwecke hat).

Daher ist ein absoluter Pfad nur ein Pfad relativ zum Stammverzeichnis.

Ein Pfad (absolut oder relativ) kann symbolische Verknüpfungen enthalten oder nicht. Wenn dies nicht der Fall ist, ist es auch etwas undurchlässig für Änderungen in der Verknüpfungsstruktur, aber dies ist nicht unbedingt erforderlich oder sogar wünschenswert. Einige Leute nennen canonical path(oder canonical file nameoder resolved path) eine, absolute pathin der alle symbolischen Verknüpfungen aufgelöst wurden, dh durch einen Pfad ersetzt wurden, zu dem sie verknüpfen. Die Befehle realpathund readlinkbeide suchen nach einem kanonischen Pfad, haben jedoch nur realpathdie Option, einen absoluten Pfad abzurufen, ohne sich die Mühe zu machen, symbolische Links aufzulösen (zusammen mit mehreren anderen Optionen, um verschiedene Arten von Pfaden abzurufen, absolut oder relativ zu einem Verzeichnis).

Dies erfordert mehrere Bemerkungen:

  1. Symbolische Links können nur aufgelöst werden, wenn bereits alles erstellt wurde, worauf sie verlinken sollen, was offensichtlich nicht immer der Fall ist. Die Befehle realpathund readlinkhaben Optionen, um dies zu berücksichtigen.
  2. Ein Verzeichnis auf einem Pfad kann später zu einer symbolischen Verknüpfung werden, was bedeutet, dass der Pfad nicht mehr vorhanden ist canonical. Daher ist das Konzept zeit- (oder umwelt-) abhängig.
  3. Selbst im Idealfall, wenn alle symbolischen Verknüpfungen aufgelöst werden können, kann canonical patheine Datei aus zwei Gründen immer noch mehrere enthalten :
    • Die Partition, die die Datei enthält, wurde möglicherweise gleichzeitig ( ro) an mehreren Einhängepunkten bereitgestellt.
    • Möglicherweise gibt es feste Links zu der Datei, was bedeutet, dass die Datei im Wesentlichen in mehreren verschiedenen Verzeichnissen vorhanden ist.

Selbst mit der viel restriktiveren Definition von canonical pathkann es daher mehrere kanonische Pfade zu einer Datei geben. Dies bedeutet auch, dass das Qualifikationsmerkmal canonicaletwas unzureichend ist, da es normalerweise einen Begriff der Einzigartigkeit impliziert.

Dies erweitert eine kurze Diskussion des Themas in einer Antwort auf eine andere ähnliche Frage bei Bash: Abrufen des absoluten Pfades, der relativ angegeben ist

Mein Fazit ist, dass realpathes besser gestaltet und viel flexibler ist als readlink. Die einzige Verwendung readlink, die nicht abgedeckt realpathist, ist der Aufruf ohne Option, der den Wert einer symbolischen Verknüpfung zurückgibt.


Es macht mir nichts aus, herabgestimmt zu werden, aber ich möchte verstehen, warum, damit ich etwas lernen kann, entweder technisch oder in Bezug auf das, was auf der Website als angemessene Praxis angesehen wird. Nun ... zumindest hat es mich veranlasst, mich bei Meta Stack Overflow zu registrieren , um die lokale Soziologie besser zu verstehen. Ich empfehle es. - Wenn jedoch jemand eine Meinung über die Unangemessenheit meiner Antwort hat, bin ich interessiert.
Babou

1
(a) Die Frage hat eine gültige Antwort von vor 2 + 1/2 Jahren. (b) Es gibt einen (einzelnen) absoluten Pfad, der einem relativen Pfad entspricht (was ich wollte), obwohl möglicherweise nicht zu einer Datei wie Ihnen wies darauf hin. Übrigens sind alle Kommentare zu realpathvs readlinkoder sogar zu symbolischen Links überschüssig zu dem, was ich gefragt habe.
Dhardy

1
Zweiter Kommentar: Kurze Antworten sind sehr oft nützlicher als lange Vorträge. Der Stapelüberlauf wird normalerweise verwendet, um bestimmte Fragen zu stellen.
Dhardy

5
1- Die Tatsache, dass eine Frage so lange eine gültige Antwort hatte, bedeutet nicht, dass sie geschlossen ist. Die Fragen sind nicht nur für den persönlichen Gebrauch bestimmt. In der Tat gibt es Abzeichen für Antworten, die mehr Stimmen als die validierte Antwort sammeln. Und mit neuen Tools kann sich die "beste" Antwort im Laufe der Zeit ändern. Viele Leute verwenden alte Antworten, auf die über die Websuche zugegriffen wird.
Babou

1
2 - Sie bestehen darauf, dass es einen (einzelnen) absoluten Pfad gibt, der einem relativen Pfad entspricht . Ich vermute zwar, was Sie unter "korrespondierend" verstehen, dh einen vom Original abgeleiteten Pfad durch eine bestimmte Menge von Transformationen, aber Ihre Aussage ist immer noch falsch. Es gibt einen eindeutigen "entsprechenden" kanonischen Pfad. Das Wort canonicalbezieht sich genau auf diese Einzigartigkeit in Bezug auf eine Reihe von Transformationen. Aber zum Beispiel ist / dev / cdrom ein vollkommen guter absoluter Pfad, obwohl es tatsächlich eine Verbindung zu / dev / sr0 ist. Beide zeigen auf dasselbe Gerät. Meine ursprüngliche Antwort zeigte auf einen relevanten Webartikel.
Babou

5

Die dogbane Antwort mit der Beschreibung, was kommt:

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

Erläuterung:

  1. Dieses Skript erhält einen relativen Pfad als Argument "$1"
  2. Dann bekommen wir DIRNAME Teil dieses Weges (können Sie entweder dir oder die Datei zu diesem Skript übergeben):dirname "$1"
  3. Dann gehen wir cd "$(dirname "$1")in dieses relative Verzeichnis und erhalten den absoluten Pfad dafür, indem wir den pwdShell-Befehl ausführen
  4. Danach hängen wir den Basisnamen an den absoluten Pfad an:$(basename "$1")
  5. Als letzten Schritt haben wir echoes geschafft

2

Denn Verzeichnisse werden dirnameausgelöst ../und zurückgegeben ./.

Die Funktion von nolan6000 kann geändert werden, um Folgendes zu beheben:

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

1
Willkommen bei SO! Bei kleinen Änderungen und Bemerkungen ist das Hinzufügen eines Kommentars zu einer vorhandenen Antwort möglicherweise angemessener als das Hinzufügen einer Antwort, insbesondere wenn dieser kopierten Antwort viele andere Informationen der ursprünglichen Antwort fehlen. Sobald Sie ein bisschen mehr Ansehen gesammelt haben, können Sie Kommentare zu den Antworten anderer Personen hinzufügen. Versuchen Sie vorerst, sich einen guten Ruf zu verschaffen, indem Sie einzigartige, wertvolle Fragen stellen oder eigenständige, gute Antworten geben.
cfi

1
Da Sie sich auf die Antwort von nolan6000 beziehen, beachten Sie bitte, dass das Poster dhardy bereits kommentiert hat, dass er die Antwort von nolan6000 nicht akzeptieren würde, da er nicht nach einem Skript sucht. Genau genommen beantwortet Ihre Antwort die Frage nicht.
cfi

Die Funktion kann hinzugefügt werden .profileund steht somit für die interaktive Verwendung zur Verfügung.
Adib

Dies funktioniert nicht, wenn $1es sich um einen einfachen Dateinamen handelt: get_abs_filename foo-> nichts (oder <current_dir>/foo/foowenn fooes sich um ein Verzeichnis handelt).
ivan_pozdeev

2

Dies ist keine Antwort auf die Frage, sondern für diejenigen, die Skripte erstellen:

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

es behandelt / .. ./ etc richtig. Ich scheine auch an OSX zu arbeiten


2

Ich habe das folgende Skript auf meinem System platziert und nenne es einen Bash-Alias, wenn ich schnell den vollständigen Pfad zu einer Datei im aktuellen Verzeichnis abrufen möchte:

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

Ich bin nicht sicher warum, aber unter OS X erweitert sich "$ PWD" auf den absoluten Pfad, wenn es von einem Skript aufgerufen wird. Wenn der Befehl find in der Befehlszeile aufgerufen wird, ist dies nicht der Fall. Aber es macht was ich will ... genießen.


$PWDhat immer den absoluten Pfad des Arbeitsverzeichnisses. Außerdem findwerden keine Schrägstriche toleriert, sodass Sie die gestellte Frage nicht beantworten. Ein schnellerer Weg, um das zu tun, wonach Sie suchen, wäre einfachecho "$PWD/$1"
Adam Katz

2

Das einfachste, wenn Sie nur integrierte Funktionen verwenden möchten, ist wahrscheinlich:

find `pwd` -name fileName

Es müssen nur zwei zusätzliche Wörter eingegeben werden. Dies funktioniert auf allen Unix-Systemen sowie unter OSX.


Ich würde -maxdepth 1vorher hinzufügen -name(vorausgesetzt, die Datei befindet sich im aktuellen Verzeichnis). Ohne das funktioniert es mit Dateien in jedem Unterverzeichnis von pwd, aber nicht mit anderen.
Walter Tross

In der Tat haben Sie Recht, die Frage hat angegeben, dass sich die Datei im aktuellen Verzeichnis befindet. Was meinst du mit "aber nicht mit anderen"?
Arj

Ich meine, ich findwerde keine Datei außerhalb des Verzeichnisbaums darunter finden pwd. Wenn Sie es beispielsweise versuchen find . -name ../existingFile, schlägt dies fehl.
Walter Tross

Fair genug, ja, dies würde voraussetzen, dass Sie den vollständigen Pfad einer Datei in Ihrem CWD (gemäß der ursprünglichen Frage) oder irgendwo in Ihrem CWD-Baum (nicht in der ursprünglichen Frage) drucken möchten.
Arj

1
#! /bin/bash

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

Dies gleicht die Mängel aus realpath, es in einem Shell-Skript zu speichern fullpath. Sie können jetzt anrufen:

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

Was löst es? realpath "foo bar"-> /home/myname/foo bar. Wenn Sie nicht die Mühe haben, Befehlszeilenargumente zu zitieren, ist dies nicht realpathdie Schuld.
ivan_pozdeev

Einverstanden, es ist eher eine Convenience-Verpackung.
ShellFish

1

Eine Alternative, um den absoluten Pfad in Ruby zu ermitteln :

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

Funktioniert ohne Argumente (aktueller Ordner) und relativen und absoluten Datei- oder Ordnerpfad als Dokument.


0

Antworte mit Homebrew

realpathist die beste Antwort, aber wenn Sie es nicht installiert haben, müssen Sie zuerst ausführen brew install coreutils, um Coreutils mit vielen fantastischen Funktionen zu installieren . Das Schreiben und Exportieren einer benutzerdefinierten Funktion ist zu viel Arbeit und Fehlerrisiko für so etwas. Hier sind zwei Zeilen:

$ brew install coreutils
$ realpath your-file-name.json 

-1

Hey Leute, ich weiß, dass es ein alter Thread ist, aber ich poste dies nur als Referenz für alle anderen, die dies wie ich besucht haben. Wenn ich die Frage richtig verstanden habe, denke ich den locate $filenameBefehl. Es zeigt den absoluten Pfad der angegebenen Datei an, jedoch nur, wenn er vorhanden ist.


4
locateist ein Dienstprogramm zum Suchen nach Dateien / Pfaden nach Namen. Es kann den Job erledigen, aber auch andere Übereinstimmungen finden und möglicherweise keine vorhandene Datei finden, ohne zuerst updatedbals root aufzurufen .
Dhardy
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.