it-swarm.com.de

Wie bekomme ich das absolute Verzeichnis einer Datei in Bash?

Ich habe ein Bash-Skript geschrieben, das eine Eingabedatei als Argument verwendet und diese liest.
Diese Datei enthält einige Pfade (relativ zu ihrem Speicherort) zu weiteren verwendeten Dateien.

Ich möchte, dass das Skript in den Ordner mit der Eingabedatei wechselt, um weitere Befehle auszuführen.

Also, wie bekomme ich den Ordner (und nur den Ordner) aus einer Eingabedatei? (In Linux.)

69
BobMcGee

Um den vollständigen Pfad zu erhalten, verwenden Sie:

readlink -f relative/path/to/file

So rufen Sie das Verzeichnis einer Datei ab:

dirname relative/path/to/file

Sie können auch die beiden kombinieren:

dirname $(readlink -f relative/path/to/file)

Ob readlink -f ist auf Ihrem System nicht verfügbar. Sie können dies verwenden*:

function myreadlink() {
  (
  cd "$(dirname $1)"         # or  cd "${1%/*}"
  echo "$PWD/$(basename $1)" # or  echo "$PWD/${1##*/}"
  )
}

Beachten Sie, dass Sie den absoluten Pfad nicht kennen müssen, wenn Sie nur in ein Verzeichnis einer Datei wechseln müssen, die als relativer Pfad angegeben ist. Ein relativer Pfad ist vollkommen legal. Verwenden Sie also einfach:

cd $(dirname relative/path/to/file)

wenn Sie zum ursprünglichen Pfad zurückkehren möchten (während das Skript ausgeführt wird), verwenden Sie pushd anstelle von cd und popd, wenn Sie fertig sind.


* Während myreadlink oben im Zusammenhang mit dieser Frage gut genug ist, gibt es einige Einschränkungen in Bezug auf das oben vorgeschlagene Werkzeug readlink. Beispielsweise folgt es einem Link zu einer Datei mit unterschiedlichem basename nicht korrekt.

134
Chen Levy

Schauen Sie sich die Manpage für realpath an, ich benutze das und so etwas wie:

CONTAININGDIR = $ (realpath $ {FILEPATH%/*})

zu tun, wie es sich anhört.

18
Richard Sitze

Dies funktioniert sowohl für Dateien als auch für Ordner:

absPath(){
    if [[ -d "$1" ]]; then
        cd "$1"
        echo "$(pwd -P)"
    else 
        cd "$(dirname "$1")"
        echo "$(pwd -P)/$(basename "$1")"
    fi
}
6
Jahid
$cat abs.sh
#!/bin/bash
echo "$(cd "$(dirname "$1")"; pwd -P)"

Einige Erklärungen:

  1. Dieses Skript erhält den relativen Pfad als Argument "$1"
  2. Dann erhalten wir dirname einen Teil dieses Pfades (Sie können diesem Skript entweder dir oder file übergeben): dirname "$1"
  3. Dann cd "$(dirname "$1"); wir in diese relative Richtung
  4. pwd -P Und erhalte den absoluten Pfad. Die Option -P Vermeidet Symlinks
  5. Als letzten Schritt echo wir es

Führen Sie dann Ihr Skript aus:

abs.sh your_file.txt
3
Eugen Konkov

Testen Sie unser neues Bash-Bibliotheksprodukt realpath-lib bei GitHub, das wir der Community kostenlos und uneingeschränkt zur Verfügung gestellt haben. Es ist sauber, einfach und gut dokumentiert und es ist großartig, daraus zu lernen. Du kannst tun:

get_realpath <absolute|relative|symlink|local file path>

Diese Funktion ist der Kern der Bibliothek:

if [[ -f "$1" ]]
then
    # file *must* exist
    if cd "$(echo "${1%/*}")" &>/dev/null
    then
        # file *may* not be local
        # exception is ./file.ext
        # try 'cd .; cd -;' *works!*
        local tmppwd="$PWD"
        cd - &>/dev/null
    else
        # file *must* be local
        local tmppwd="$PWD"
    fi
else
    # file *cannot* exist
    return 1 # failure
fi

# reassemble realpath
echo "$tmppwd"/"${1##*/}"
return 0 # success

}

Es ist Bash 4+, erfordert keine Abhängigkeiten und enthält außerdem get_dirname, get_filename, get_stemname und validate_path.

1
AsymLabs

Problem mit der obigen Antwort kommt mit Dateien mit "./" wie "./my-file.txt"

Problemumgehung (von vielen):

    myfile="./somefile.txt"
    FOLDER="$(dirname $(readlink -f "${ARG}"))"
    echo ${FOLDER}
0
Mike Q