Frage

Wie erhalte ich den Pfad des Verzeichnisses, in dem sich a Bash Skript befindet sich, innen dieses Skript?

Nehmen wir zum Beispiel an, ich möchte ein Bash-Skript als Startprogramm für eine andere Anwendung verwenden.Ich möchte das Arbeitsverzeichnis in das Verzeichnis ändern, in dem sich das Bash-Skript befindet, damit ich die Dateien in diesem Verzeichnis bearbeiten kann, etwa so:

$ ./application
War es hilfreich?

Lösung

#!/bin/bash

DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd )"

ist ein nützliches Einzeiler, die Ihnen die vollständigen Verzeichnisnamen des Skripts geben, egal, woher sie aufgerufen wird.

Es wird funktionieren, solange die letzte Komponente des Pfades verwendet, um das Skript zu finden ist kein symbolischer Link (Verzeichnis Links sind in Ordnung). Wenn Sie auch keine Links zu dem Script lösen wollen selbst, müssen Sie eine mehrzeilige Lösung:

#!/bin/bash

SOURCE="${BASH_SOURCE[0]}"
while [ -h "$SOURCE" ]; do # resolve $SOURCE until the file is no longer a symlink
  DIR="$( cd -P "$( dirname "$SOURCE" )" >/dev/null 2>&1 && pwd )"
  SOURCE="$(readlink "$SOURCE")"
  [[ $SOURCE != /* ]] && SOURCE="$DIR/$SOURCE" # if $SOURCE was a relative symlink, we need to resolve it relative to the path where the symlink file was located
done
DIR="$( cd -P "$( dirname "$SOURCE" )" >/dev/null 2>&1 && pwd )"

Das letzte wird mit einer beliebigen Kombination von Alias-Namen arbeiten, source, bash -c, Symlinks, etc.

Vorsicht: Wenn Sie in ein anderes Verzeichnis cd bevor dieses Snippet ausgeführt wird, ist das Ergebnis falsch sein kann!

Auch achten Sie auf $CDPATH gotchas und stderr Ausgabe Nebenwirkungen, wenn der Benutzer intelligent cd Ausgabe zu umleiten außer Kraft gesetzt hat, anstatt zu stderr (einschließlich Escape-Sequenzen, wie wenn update_terminal_cwd >&2 auf Mac Aufruf). Hinzufügen >/dev/null 2>&1 am Ende Ihres cd Befehl kümmert sich um beide Möglichkeiten.

Um zu verstehen, wie es funktioniert, versuchen, diese ausführliche Form ausgeführt wird:

#!/bin/bash

SOURCE="${BASH_SOURCE[0]}"
while [ -h "$SOURCE" ]; do # resolve $SOURCE until the file is no longer a symlink
  TARGET="$(readlink "$SOURCE")"
  if [[ $TARGET == /* ]]; then
    echo "SOURCE '$SOURCE' is an absolute symlink to '$TARGET'"
    SOURCE="$TARGET"
  else
    DIR="$( dirname "$SOURCE" )"
    echo "SOURCE '$SOURCE' is a relative symlink to '$TARGET' (relative to '$DIR')"
    SOURCE="$DIR/$TARGET" # if $SOURCE was a relative symlink, we need to resolve it relative to the path where the symlink file was located
  fi
done
echo "SOURCE is '$SOURCE'"
RDIR="$( dirname "$SOURCE" )"
DIR="$( cd -P "$( dirname "$SOURCE" )" >/dev/null 2>&1 && pwd )"
if [ "$DIR" != "$RDIR" ]; then
  echo "DIR '$RDIR' resolves to '$DIR'"
fi
echo "DIR is '$DIR'"

Und es wird Druck etwas wie:

SOURCE './scriptdir.sh' is a relative symlink to 'sym2/scriptdir.sh' (relative to '.')
SOURCE is './sym2/scriptdir.sh'
DIR './sym2' resolves to '/home/ubuntu/dotfiles/fo fo/real/real1/real2'
DIR is '/home/ubuntu/dotfiles/fo fo/real/real1/real2'

Andere Tipps

Verwenden dirname "$0":

#!/bin/bash
echo "The script you are running has basename `basename "$0"`, dirname `dirname "$0"`"
echo "The present working directory is `pwd`"

mit pwd allein wird nicht funktionieren, wenn Sie nicht das Skript aus dem Verzeichnis ausgeführt werden, es in enthalten ist.

[matt@server1 ~]$ pwd
/home/matt
[matt@server1 ~]$ ./test2.sh
The script you are running has basename test2.sh, dirname .
The present working directory is /home/matt
[matt@server1 ~]$ cd /tmp
[matt@server1 tmp]$ ~/test2.sh
The script you are running has basename test2.sh, dirname /home/matt
The present working directory is /tmp

Der dirname Befehl ist die einfachste, einfach den Pfades Parsen aus dem $ 0 (Skriptname) Variable auf die Dateinamen auf:

dirname "$0"

Aber, wie matt b wies darauf hin, kehrte der Pfad unterschiedlich ist, je nachdem wie das Skript aufgerufen wird. PWD macht den Job nicht, weil, dass man nur sagt, was das aktuelle Verzeichnis, nicht das, was Verzeichnis das Skript befindet sich in. Außerdem, wenn ein symbolischer Link zu einem Skript ausgeführt wird, Sie gehen einen (wahrscheinlich relative) Pfad bekommen wo befindet sich der Link, nicht das eigentliche Skript.

Einige andere erwähnt haben die readlink Befehl, aber am einfachsten, können Sie:

dirname "$(readlink -f "$0")"

readlink wird das Skript Pfad zu einem absoluten Pfad von der Wurzel des Dateisystems lösen. So werden alle Pfade, die einzelne oder doppelte Punkte, Tilden und / oder symbolische Links werden zu einem vollständigen Pfad aufgelöst werden.

Hier ist ein Skript jedes dieser demonstrieren, whatdir.sh:

#!/bin/bash
echo "pwd: `pwd`"
echo "\$0: $0"
echo "basename: `basename $0`"
echo "dirname: `dirname $0`"
echo "dirname/readlink: $(dirname $(readlink -f $0))"

Wenn Sie dieses Skript in meinem Home-Verzeichnis, einen relativen Pfad:

>>>$ ./whatdir.sh 
pwd: /Users/phatblat
$0: ./whatdir.sh
basename: whatdir.sh
dirname: .
dirname/readlink: /Users/phatblat

Auch hier aber mit dem vollständigen Pfad zum Skript:

>>>$ /Users/phatblat/whatdir.sh 
pwd: /Users/phatblat
$0: /Users/phatblat/whatdir.sh
basename: whatdir.sh
dirname: /Users/phatblat
dirname/readlink: /Users/phatblat

Jetzt ändert Verzeichnisse:

>>>$ cd /tmp
>>>$ ~/whatdir.sh 
pwd: /tmp
$0: /Users/phatblat/whatdir.sh
basename: whatdir.sh
dirname: /Users/phatblat
dirname/readlink: /Users/phatblat

Und schließlich eine symbolische Verknüpfung mit dem Skript auszuführen:

>>>$ ln -s ~/whatdir.sh whatdirlink.sh
>>>$ ./whatdirlink.sh 
pwd: /tmp
$0: ./whatdirlink.sh
basename: whatdirlink.sh
dirname: .
dirname/readlink: /Users/phatblat
pushd . > /dev/null
SCRIPT_PATH="${BASH_SOURCE[0]}"
if ([ -h "${SCRIPT_PATH}" ]); then
  while([ -h "${SCRIPT_PATH}" ]); do cd `dirname "$SCRIPT_PATH"`; 
  SCRIPT_PATH=`readlink "${SCRIPT_PATH}"`; done
fi
cd `dirname ${SCRIPT_PATH}` > /dev/null
SCRIPT_PATH=`pwd`;
popd  > /dev/null

Funktioniert für alle Versionen, einschließlich

  • , wenn sie über multple Tiefen Soft-Link genannt,
  • , wenn die Datei, um sie
  • wenn Skript mit dem Befehl "source" aka . (dot) Operator genannt.
  • wenn arg $0 aus Anrufer geändert.
  • "./script"
  • "/full/path/to/script"
  • "/some/path/../../another/path/script"
  • "./some/folder/script"

Wenn alternativ der Bash-Skript selbst ein relativ Symlink ist Sie wollen es zu folgen und gibt den vollständigen Pfad der verlinkten Skript:

pushd . > /dev/null
SCRIPT_PATH="${BASH_SOURCE[0]}";
if ([ -h "${SCRIPT_PATH}" ]) then
  while([ -h "${SCRIPT_PATH}" ]) do cd `dirname "$SCRIPT_PATH"`; SCRIPT_PATH=`readlink "${SCRIPT_PATH}"`; done
fi
cd `dirname ${SCRIPT_PATH}` > /dev/null
SCRIPT_PATH=`pwd`;
popd  > /dev/null

SCRIPT_PATH in vollständigem Pfad angegeben wird, unabhängig davon, wie sie genannt wird.
So stellen Sie sicher das das Skripts beim Start finden.

Dieser Kommentar und Code Copyleft, wählbare Lizenz unter der folgenden GPL2.0- oder später oder CC-SA 3.0 (Creative Share Alike) oder höher. (C) 2008. Alle Rechte vorbehalten. Keine Gewährleistung jeglicher Art. Sie wurden gewarnt.
http://www.gnu.org/licenses/gpl-2.0.txt
http://creativecommons.org/licenses/by-sa/3.0/
18eedfe1c99df68dc94d4a94712a71aaa8e1e9e36cacf421b9463dd2bbaa02906d0d6656

Kurze Antwort:

`dirname $0`

oder ( vorzugsweise ):

$(dirname "$0")

Sie können $ BASH_SOURCE

verwenden
#!/bin/bash

scriptdir=`dirname "$BASH_SOURCE"`

Beachten Sie, dass Sie #! / Bin / bash und nicht die #! / Bin / sh seit seiner einer Bash Erweiterung

verwenden müssen

Das sollte es tun:

DIR=$(dirname "$(readlink -f "$0")")

Arbeiten mit symbolischen Links und Leerzeichen in Pfad. Siehe man Seiten für dirname und readlink .

Edit:

Von der Kommentarspur scheint es nicht mit Mac OS zu arbeiten. Ich habe keine Ahnung, warum das so ist. Irgendwelche Vorschläge?

pwd verwendet werden kann, das aktuelle Arbeitsverzeichnis zu finden, und dirname das Verzeichnis einer bestimmten Datei zu finden (Befehl, der ausgeführt wurde, ist $0, so dirname $0 sollten Sie das Verzeichnis des aktuellen Skripts geben).

Allerdings gibt dirname genau das Verzeichnis Teil des Dateinamens, die eher als nicht auf das aktuelle Arbeitsverzeichnis ist relativ wird. Wenn Ihr Skript Verzeichnis aus irgendeinem Grund geändert werden muss, dann wird die Ausgabe von dirname bedeutungslos wird.

Ich schlage vor, wie folgt vor:

#!/bin/bash

reldir=`dirname $0`
cd $reldir
directory=`pwd`

echo "Directory is $directory"

Auf diese Weise erhalten Sie ein absolutes, sondern dann relativ Verzeichnis.

Da das Skript wird in einer separaten bash-Instanz ausgeführt wird, besteht keine Notwendigkeit, das Arbeitsverzeichnis danach wieder herzustellen, aber wenn Sie aus irgendeinem Grunde wollen, um wieder in Ihrem Skript zu ändern, können Sie leicht den Wert von pwd zuweisen eine Variable, bevor Sie Verzeichnis ändern, für die zukünftige Verwendung.

Obwohl nur

cd `dirname $0`

löst das spezifische Szenario in der Frage, finde ich mit dem absoluten Pfad zu mehr nützlicher im Allgemeinen.

Ich glaube nicht, das so einfach ist, wie andere es gemacht haben, zu sein. PWD nicht funktioniert, wie das aktuelle Verzeichnis nicht unbedingt das Verzeichnis mit dem Skript. $ 0 hat nicht immer die Informationen auch nicht. Betrachten Sie die folgenden drei Möglichkeiten, ein Skript aufgerufen werden kann.

./script

/usr/bin/script

script

In den ersten und dritten Wegen $ 0 hat nicht die vollständige Pfad Info. In der zweiten und dritten, pwd nicht funktionieren. Der einzige Weg, die dir im dritten Weg zu bekommen wäre über den Weg zu laufen und die Datei mit dem richtigen Spiel zu finden. Grundsätzlich ist der Code würde wiederholen, was das Betriebssystem der Fall ist.

Eine Möglichkeit, zu tun, was Sie würden fragen, nur die Daten codieren im Verzeichnis / usr / share dir, und es durch vollständigen Pfad zu verweisen. Daten shoudn't im Verzeichnis / usr / bin dir sowieso, so ist dies wahrscheinlich die Sache zu tun.

SCRIPT_DIR=$( cd ${0%/*} && pwd -P )

Dies wird das aktuelle Arbeitsverzeichnis auf Mac OS X 10.6.6:

DIR=$(cd "$(dirname "$0")"; pwd)
$(dirname "$(readlink -f "$BASH_SOURCE")")

Ich bin es müde, immer und immer wieder auf dieser Seite kommen, um die Einzeiler in der akzeptierten Antwort kopieren einfügen. Das Problem mit dieser ist es nicht leicht zu verstehen und merken ist.

Hier ist eine einfach zu merkende Skript:

DIR=$(dirname "${BASH_SOURCE[0]}")  # get the directory name
DIR=$(realpath "${DIR}")    # resolve its full path if need be

Dies ist Linux-spezifisch, aber man konnte verwenden:

SELF=$(readlink /proc/$$/fd/255)

Hier ist ein POSIX-kompatibel Einzeiler:

SCRIPT_PATH=`dirname "$0"`; SCRIPT_PATH=`eval "cd \"$SCRIPT_PATH\" && pwd"`

# test
echo $SCRIPT_PATH

habe ich versucht, jede einzelne dieser und keiner von ihnen arbeitete. Einer war ganz in der Nähe, aber hatte einen kleinen Fehler, der es schlecht brach; sie vergessen, den Pfad in Anführungszeichen zu wickeln.

Auch viele Leute annehmen, dass Sie das Skript von einem Shell laufen lassen, so vergessen, wenn Sie ein neues Skript öffnen wird standardmäßig nach Hause.

Versuchen Sie dieses Verzeichnis für Größe:

/ var / No one / Gedanken / über Spaces Sein / In einem Verzeichnis / Namen / Und hier Ihr file.text

Dies macht es richtig egal, wie oder wo Sie es ausführen.

#!/bin/bash
echo "pwd: `pwd`"
echo "\$0: $0"
echo "basename: `basename "$0"`"
echo "dirname: `dirname "$0"`"

So macht es sich hier tatsächlich nützlich ist, wie Sie in das Verzeichnis des laufenden Skript ändern:

cd "`dirname "$0"`"

Ich hoffe, das hilft

Hier ist die einfache, korrekte Art und Weise:

actual_path=$(readlink -f "${BASH_SOURCE[0]}")
script_dir=$(dirname "$actual_path")

Erklärung:

  • ${BASH_SOURCE[0]} - der vollständige Pfad zum Skript. Der Wert wird dies korrekt sein, auch wenn das Skript bezogen wird, z.B. source <(echo 'echo $0') druckt bash , während es mit ${BASH_SOURCE[0]} ersetzt wird den vollständigen Pfad des Skripts drucken. (Natürlich ist dies vorausgesetzt, dass Sie OK sind eine Abhängigkeit von Bash nehmen.)

  • readlink -f - Recursively löst alle Symlinks in dem angegebenen Pfad. Dies ist eine GNU-Erweiterung, und nicht auf (zum Beispiel) BSD-Systemen. Wenn Sie einen Mac verwenden, können Sie Homebrew verwenden, um GNU coreutils zu installieren und ersetzen diese mit greadlink -f .

  • Und natürlich dirname wird das übergeordnete Verzeichnis des Pfades.

Ich würde so etwas wie folgt verwenden:

# retrieve the full pathname of the called script
scriptPath=$(which $0)

# check whether the path is a link or not
if [ -L $scriptPath ]; then

    # it is a link then retrieve the target path and get the directory name
    sourceDir=$(dirname $(readlink -f $scriptPath))

else

    # otherwise just get the directory name of the script path
    sourceDir=$(dirname $scriptPath)

fi

Eine leichte Überarbeitung der Lösung e-satis und 3bcdnlklvc04a wies darauf hin, in ihre Antwort

SCRIPT_DIR=''
pushd "$(dirname "$(readlink -f "$BASH_SOURCE")")" > /dev/null && {
    SCRIPT_DIR="$PWD"
    popd > /dev/null
}    

Dies sollte immer noch funktionieren in allen Fällen sie wollten.

EDIT: verhindert popd nach gescheiterten pushd dank konsolebox

#!/bin/sh
PRG="$0"

# need this for relative symlinks
while [ -h "$PRG" ] ; do
   PRG=`readlink "$PRG"`
done

scriptdir=`dirname "$PRG"`

$_ ist als Alternative zu $0 erwähnenswert.Wenn Sie ein Skript über Bash ausführen, kann die akzeptierte Antwort wie folgt gekürzt werden:

DIR="$( dirname "$_" )"

Beachten Sie, dass dies die erste Anweisung in Ihrem Skript sein muss.

Ich habe viele Antworten gegeben verglichen und kommen mit einigen kompaktere Lösungen. Diese scheinen all die verrückten Rand Fälle zu behandeln, die aus Ihrer Lieblings-Kombination entstehen aus:

  • Absolute Pfade oder relative Pfade
  • Datei- und Verzeichnis Soft-Links
  • Invocation als script, bash script, bash -c script, source script oder . script
  • Spaces, Tabs, Zeilenumbrüche, Unicode usw. in Verzeichnissen und / oder Dateinamen
  • Dateinamen mit einem Bindestrich beginnen

Wenn Sie von Linux laufen lassen, es scheint, dass der proc Griff verwendet, ist die beste Lösung, die vollständig aufgelöste Quelle des aktuell laufenden Skript (in einer interaktiven Sitzung, die Verbindungspunkte auf den jeweiligen /dev/pts/X) zu finden:

resolved="$(readlink /proc/$$/fd/255 && echo X)" && resolved="${resolved%$'\nX'}"

Dies hat ein kleines bisschen Hässlichkeit, aber die Lösung ist kompakt und leicht zu verstehen. Wir verwenden nicht bash Primitive nur, aber ich bin okay, dass mit, weil readlink erheblich die Aufgabe vereinfacht. Die echo X fügt eine X bis zum Ende des variablen String, so dass jedes nachfolgendes Leerzeichen im Dateinamen nicht gegessen erhält, und der Parameter Substitution ${VAR%X} am Ende der Zeile wird des X befreien. Da readlink eine neue Zeile der eigenen fügt (die normalerweise in der Befehlssubstitution gegessen würde, wenn nicht für unsere bisherigen Tricks), müssen wir davon loszuwerden, auch. Dies geschieht am einfachsten erreicht das $'' zitierte Schema verwendet, die wir Escape-Sequenzen wie \n darzustellen Zeilenumbrüche verwenden kann (dies ist auch, wie Sie leicht deviously Namen Verzeichnisse und Dateien machen können).

Die oben sollte Ihre Bedürfnisse decken die derzeit laufende Skript unter Linux zum Lokalisieren, aber wenn Sie nicht über das proc Dateisystem zur Verfügung haben, oder wenn Sie versuchen, den vollständig aufgelösten Pfad einer anderen Datei zu suchen, dann vielleicht werden Sie die folgenden Code hilfreich. Es ist nur eine geringfügige Modifikation der oben Einzeiler. Wenn Sie spielen, um mit fremden Verzeichnis / Dateinamen, die Überprüfung der Ausgang sowohl mit ls und readlink ist informativ, wie ls gibt „vereinfachte“ Pfade, unter Substitution von ? für Dinge wie Zeilenumbrüchen.

absolute_path=$(readlink -e -- "${BASH_SOURCE[0]}" && echo x) && absolute_path=${absolute_path%?x}
dir=$(dirname -- "$absolute_path" && echo x) && dir=${dir%?x}
file=$(basename -- "$absolute_path" && echo x) && file=${file%?x}

ls -l -- "$dir/$file"
printf '$absolute_path: "%s"\n' "$absolute_path"

Versuchen Sie es mit:

real=$(realpath $(dirname $0))

Für Systeme GNU coreutils Readlink mit (zB Linux.):

$(readlink -f "$(dirname "$0")")

Keine Notwendigkeit BASH_SOURCE verwenden, wenn $0 den Skript Dateinamen enthält.

So ... Ich glaube, ich dieses habe. Spät zur Party, aber ich glaube, dass einige es hier zu sein schätzen ist, sie über diesen Thread kommen. Die Kommentare sollten erklären.

#!/bin/sh # dash bash ksh # !zsh (issues). G. Nixon, 12/2013. Public domain.

## 'linkread' or 'fullpath' or (you choose) is a little tool to recursively
## dereference symbolic links (ala 'readlink') until the originating file
## is found. This is effectively the same function provided in stdlib.h as
## 'realpath' and on the command line in GNU 'readlink -f'.

## Neither of these tools, however, are particularly accessible on the many
## systems that do not have the GNU implementation of readlink, nor ship
## with a system compiler (not to mention the requisite knowledge of C).

## This script is written with portability and (to the extent possible, speed)
## in mind, hence the use of printf for echo and case statements where they
## can be substituded for test, though I've had to scale back a bit on that.

## It is (to the best of my knowledge) written in standard POSIX shell, and
## has been tested with bash-as-bin-sh, dash, and ksh93. zsh seems to have
## issues with it, though I'm not sure why; so probably best to avoid for now.

## Particularly useful (in fact, the reason I wrote this) is the fact that
## it can be used within a shell script to find the path of the script itself.
## (I am sure the shell knows this already; but most likely for the sake of
## security it is not made readily available. The implementation of "$0"
## specificies that the $0 must be the location of **last** symbolic link in
## a chain, or wherever it resides in the path.) This can be used for some
## ...interesting things, like self-duplicating and self-modifiying scripts.

## Currently supported are three errors: whether the file specified exists
## (ala ENOENT), whether its target exists/is accessible; and the special
## case of when a sybolic link references itself "foo -> foo": a common error
## for beginners, since 'ln' does not produce an error if the order of link
## and target are reversed on the command line. (See POSIX signal ELOOP.)

## It would probably be rather simple to write to use this as a basis for
## a pure shell implementation of the 'symlinks' util included with Linux.

## As an aside, the amount of code below **completely** belies the amount
## effort it took to get this right -- but I guess that's coding for you.

##===-------------------------------------------------------------------===##

for argv; do :; done # Last parameter on command line, for options parsing.

## Error messages. Use functions so that we can sub in when the error occurs.

recurses(){ printf "Self-referential:\n\t$argv ->\n\t$argv\n" ;}
dangling(){ printf "Broken symlink:\n\t$argv ->\n\t"$(readlink "$argv")"\n" ;}
errnoent(){ printf "No such file: "$@"\n" ;} # Borrow a horrible signal name.

# Probably best not to install as 'pathfull', if you can avoid it.

pathfull(){ cd "$(dirname "$@")"; link="$(readlink "$(basename "$@")")"

## 'test and 'ls' report different status for bad symlinks, so we use this.

 if [ ! -e "$@" ]; then if $(ls -d "$@" 2>/dev/null) 2>/dev/null;  then
    errnoent 1>&2; exit 1; elif [ ! -e "$@" -a "$link" = "$@" ];   then
    recurses 1>&2; exit 1; elif [ ! -e "$@" ] && [ ! -z "$link" ]; then
    dangling 1>&2; exit 1; fi
 fi

## Not a link, but there might be one in the path, so 'cd' and 'pwd'.

 if [ -z "$link" ]; then if [ "$(dirname "$@" | cut -c1)" = '/' ]; then
   printf "$@\n"; exit 0; else printf "$(pwd)/$(basename "$@")\n"; fi; exit 0
 fi

## Walk the symlinks back to the origin. Calls itself recursivly as needed.

 while [ "$link" ]; do
   cd "$(dirname "$link")"; newlink="$(readlink "$(basename "$link")")"
   case "$newlink" in
    "$link") dangling 1>&2 && exit 1                                       ;;
         '') printf "$(pwd)/$(basename "$link")\n"; exit 0                 ;;
          *) link="$newlink" && pathfull "$link"                           ;;
   esac
 done
 printf "$(pwd)/$(basename "$newlink")\n"
}

## Demo. Install somewhere deep in the filesystem, then symlink somewhere 
## else, symlink again (maybe with a different name) elsewhere, and link
## back into the directory you started in (or something.) The absolute path
## of the script will always be reported in the usage, along with "$0".

if [ -z "$argv" ]; then scriptname="$(pathfull "$0")"

# Yay ANSI l33t codes! Fancy.
 printf "\n\033[3mfrom/as: \033[4m$0\033[0m\n\n\033[1mUSAGE:\033[0m   "
 printf "\033[4m$scriptname\033[24m [ link | file | dir ]\n\n         "
 printf "Recursive readlink for the authoritative file, symlink after "
 printf "symlink.\n\n\n         \033[4m$scriptname\033[24m\n\n        "
 printf " From within an invocation of a script, locate the script's "
 printf "own file\n         (no matter where it has been linked or "
 printf "from where it is being called).\n\n"

else pathfull "$@"
fi

Versuchen Sie, die folgenden Quer kompatible Lösung:

CWD="$(cd -P -- "$(dirname -- "$0")" && pwd -P)"

als realpath oder readlink Befehle nicht immer verfügbar ist (je nach Betriebssystem) und ${BASH_SOURCE[0]} ist nur in bash.

Alternativ können Sie die folgende Funktion in bash versuchen:

realpath () {
  [[ $1 = /* ]] && echo "$1" || echo "$PWD/${1#./}"
}

Diese Funktion nimmt ein Argument. Wenn Argument bereits absoluten Pfad hat, drucken Sie es, wie es ist, sonst $PWD Variable + Argument Dateiname gedruckt werden (ohne ./ Präfix).

Siehe auch:

Hmm, wenn im Pfad Basisnamen & dirname geht einfach nicht schneiden und den Weg zu Fuß ist hart (was ist, wenn Eltern ausführte PATH nicht!). Allerdings hat die Schale einen offenen Griff zu seinem Skript haben, und in bash der Griff # 255.

SELF=`readlink /proc/$$/fd/255`

funktioniert für mich.

Zu viele Antworten zusammenzufassen:

    Script: "/tmp/src dir/test.sh"
    Calling folder: "/tmp/src dir/other"

verwendete Befehle

    echo Script-Dir : `dirname "$(realpath $0)"`
    echo Script-Dir : $( cd ${0%/*} && pwd -P )
    echo Script-Dir : $(dirname "$(readlink -f "$0")")
    echo
    echo Script-Name : `basename "$(realpath $0)"`
    echo Script-Name : `basename $0`
    echo
    echo Script-Dir-Relative : `dirname "$BASH_SOURCE"`
    echo Script-Dir-Relative : `dirname $0`
    echo
    echo Calling-Dir : `pwd`

Die Ausgabe:

     Script-Dir : /tmp/src dir
     Script-Dir : /tmp/src dir
     Script-Dir : /tmp/src dir

     Script-Name : test.sh
     Script-Name : test.sh

     Script-Dir-Relative : ..
     Script-Dir-Relative : ..

     Calling-Dir : /tmp/src dir/other

Siehe https://pastebin.com/J8KjxrPF

Dies funktioniert in der Bash-3.2:

path="$( dirname "$( which "$0" )" )"

Hier ist ein Beispiel für die Verwendung:

Angenommen, Sie haben eine ~ / bin Verzeichnis, das in der $ PATH ist . Sie haben Skript A in diesem Verzeichnis. Es source s Skript ~ / bin / lib / B . Sie wissen, wo das mitgelieferte Skript zum Original ein relativ (das Unterverzeichnis lib ), aber nicht, wo es auf die Benutzer aktuellen Verzeichnis relativ ist.

Dies wird gelöst durch die folgenden Punkte (innerhalb von A ):

source "$( dirname "$( which "$0" )" )/lib/B"

Es spielt keine Rolle, wo der Benutzer ist oder wie er das Skript aufruft, wird dies immer funktioniert.

Keine von diesen für ein Bash-Skript von Finder in OS X gestartet gearbeitet - ich landete mit:

SCRIPT_LOC="`ps -p $$ | sed /PID/d | sed s:.*/Network/:/Network/: |
sed s:.*/Volumes/:/Volumes/:`"

Nicht schön, aber es wird die Arbeit getan.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top