Rufen Sie das Quellverzeichnis eines Bash-Skripts aus dem Skript selbst ab
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
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
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üssenDas 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 GNUcoreutils
zu installieren und ersetzen diese mitgreadlink -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
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.