Obtenir le répertoire source d'un script Bash de l'intérieur

Comment puis-je obtenir le chemin du répertoire dans lequel se trouve un script Bash , à l'intérieur de ce script?

par exemple, disons que je veux utiliser un script Bash comme lanceur pour une autre application. Je veux changer le répertoire de travail en celui où se trouve le script Bash, donc je peux opérer sur les fichiers de ce répertoire, comme ceci:

$ ./application
4059
demandé sur Jiaaro 2008-09-13 00:39:56

30 réponses

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

est un liner utile qui vous donnera le nom complet du répertoire du script peu importe d'où il est appelé.

il fonctionnera aussi longtemps que le dernier composant du chemin utilisé pour trouver le script n'est pas un lien symbolique (les liens de répertoire sont OK). Si vous souhaitez également résoudre tout lien vers le script lui-même, vous avez besoin d'une solution multi-ligne:

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 && 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 && pwd )"

Ce dernier fonctionnera avec n'importe quelle combinaison de alias, source , bash -c , les liens symboliques, etc.

attention: si vous cd dans un répertoire différent avant d'exécuter cet extrait, le résultat peut être incorrect! En outre, attention à $CDPATH gotchas .

Pour comprendre comment cela fonctionne, essayez d'exécuter cette plus prolixe:

#!/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" )" && pwd )"
if [ "$DIR" != "$RDIR" ]; then
  echo "DIR '$RDIR' resolves to '$DIR'"
fi
echo "DIR is '$DIR'"

et il imprimera quelque chose comme:

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'
5400
répondu Dave Dopson 2018-07-14 04:57:44

utiliser dirname ""151920920"" :

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

utiliser pwd seul ne fonctionnera pas si vous n'exécutez pas le script à partir du répertoire dans lequel il est contenu.

[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
686
répondu matt b 2018-03-29 22:51:06

la commande dirname est la plus basique, en analysant simplement le chemin jusqu'au nom du fichier hors de la variable $0 (Nom du script):

dirname ""151900920""

mais, comme matt b l'a souligné, le chemin retourné est différent selon la façon dont le script est appelé. pwd ne fait pas le travail parce que cela ne fait que vous dire ce qu'est le répertoire courant, pas dans quel répertoire le script réside. En outre, si un lien symbolique vers un script est exécuté, vous allez pour obtenir un chemin (probablement relatif) à l'endroit où le lien réside, pas le script réel.

D'autres ont mentionné la commande readlink , mais à sa plus simple, vous pouvez utiliser:

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

readlink résoudra le chemin du script vers un chemin absolu à partir de la racine du système de fichiers. Ainsi, tous les chemins contenant des points simples ou doubles, des tildes et/ou des liens symboliques seront résolus à un chemin complet.

Voici un script montrant chacun d'eux, whatdir.sh:

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

exécuter ce script dans mon répertoire personnel, en utilisant un chemin relatif:

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

encore une fois, mais en utilisant le chemin complet vers le script:

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

change maintenant les répertoires:

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

et enfin l'utilisation d'un lien symbolique pour exécuter le script:

>>>$ ln -s ~/whatdir.sh whatdirlink.sh
>>>$ ./whatdirlink.sh 
pwd: /tmp
"151960920": ./whatdirlink.sh
basename: whatdirlink.sh
dirname: .
dirname/readlink: /Users/phatblat
382
répondu phatblat 2017-01-04 16:33:10
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

fonctionne pour toutes les versions,y compris

  • lorsqu'il est appelé par de multiples profondeur doux lien,
  • quand le fichier il
  • quand script appelé par commande " source "alias . (dot) de l'opérateur.
  • quand arg "151940920" est modifié de l'appelant.
  • "./script"
  • "/full/path/to/script"
  • "/some/path/../../another/path/script"
  • "./some/folder/script"

alternativement, si le script bash lui-même est un symlink relatif vous want suivre et retourner le chemin complet du script lié:

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 est donné dans le chemin complet, peu importe comment il est appelé.

Assurez-vous de localiser ce au début du script.

ce commentaire et ce code Copyleft, licence sélectionnable sous la GPL 2.0 ou plus tard ou CC-SA 3.0 (CreativeCommons Share Alike) ou plus tard. (C) 2008. Tous droits réservés. Aucune garantie d'aucune sorte. Vous avez été averti.

http://www.gnu.org/licenses/gpl-2.0.txt

http://creativecommons.org/licenses/by-sa/3.0/

18eedfe1c99df68dc94d4a94712a71aa8e1e9e36cacf421b9463dd2bbaa02906d0d6656

168
répondu user25866 2018-05-17 11:21:43

courte réponse:

`dirname "151900920"`

ou ( de préférence ):

$(dirname ""151910920"")
94
répondu Fabien 2017-04-19 06:59:25

vous pouvez utiliser $BASH_SOURCE

#!/bin/bash

scriptdir=`dirname "$BASH_SOURCE"`

Notez que vous devez utiliser #!/bin/bash et pas #!/bin/sh depuis sa un bash extension

91
répondu Mr Shark 2014-06-17 10:12:50

Cela devrait le faire:

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

fonctionne avec des liens symboliques et des espaces dans le chemin. Voir les pages de manuel pour dirname et readlink .

Edit:

dans le commentaire de la piste, il semble ne pas fonctionner avec Mac OS. Je n'ai aucune idée pourquoi. Toutes les suggestions?

58
répondu Simon Rigét 2017-07-29 22:04:57

pwd peut être utilisé pour trouver le répertoire de travail courant, et dirname pour trouver le répertoire d'un fichier particulier (la commande a été exécutée, est "151940920" , donc dirname "151950920" devrait vous donner le répertoire du script courant).

Toutefois, dirname donne précisément le répertoire partie du nom du fichier, ce qui est plus probable qu'improbable va être relatif au répertoire de travail courant. Si votre script doit changer de répertoire pour certains la raison, alors la sortie de dirname devient insignifiante.

je suggère ce qui suit:

#!/bin/bash

reldir=`dirname "151900920"`
cd $reldir
directory=`pwd`

echo "Directory is $directory"

de cette façon, vous obtenez un répertoire absolu, plutôt que relatif.

étant donné que le script sera exécuté dans une instance de bash séparée, il n'est pas nécessaire de restaurer le répertoire de travail par la suite, mais si vous voulez modifier votre script pour une raison quelconque, vous pouvez facilement attribuer la valeur pwd à un variable avant de changer de répertoire, pour une utilisation future.

bien que juste

cd `dirname "151910920"`

résout le scénario spécifique dans la question, je trouve avoir le chemin absolu vers plus utile en général.

51
répondu SpoonMeiser 2016-04-01 15:23:56

je ne pense pas que ce soit aussi facile que d'autres l'ont fait pour l'être. pwd ne fonctionne pas, comme le répertoire courant n'est pas nécessairement le répertoire du script. $0 n'a pas toujours les infos. Considérer trois façons d'appeler un script.

./script

/usr/bin/script

script

dans les première et troisième voies $0 n'a pas les informations complètes de chemin. Dans le deuxième et le troisième cas, le pwd ne fonctionne pas. La seule façon d'obtenir la dir dans la troisième voie serait de courir à travers le chemin et trouver le fichier avec la correspondance correcte. En gros, le code devrait refaire ce que le système D'exploitation fait.

une façon de faire ce que vous demandez serait de simplement coder les données dans le répertoire /usr/share, et de les référencer par le chemin complet. Les données ne devraient pas être dans le répertoire /usr/bin de toute façon, donc c'est probablement la chose à faire.

32
répondu 2 revs, 2 users 83%Jim 2011-12-02 14:56:57
SCRIPT_DIR=$( cd ${0%/*} && pwd -P )
31
répondu P M 2013-05-30 11:28:27

ceci obtient le répertoire de travail courant sur Mac OS X 10.6.6:

DIR=$(cd "$(dirname ""151900920"")"; pwd)
24
répondu Pubguy 2012-12-03 13:29:20

C'est spécifique à Linux, mais vous pouvez utiliser:

SELF=$(readlink /proc/$$/fd/255)
24
répondu Steve Baker 2013-12-22 00:07:53
$(dirname "$(readlink -f "$BASH_SOURCE")")
24
répondu test11 2018-05-13 04:36:30

Voici une doublure unique conforme à POSIX:

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

# test
echo $SCRIPT_PATH
20
répondu lamawithonel 2013-04-15 07:28:08

j'ai essayé chacun de ceux-ci et aucun d'eux n'a fonctionné. L'un d'eux était très proche, mais il avait un petit insecte qui le cassait mal; ils ont oublié d'envelopper le chemin dans des guillemets.

beaucoup de gens pensent aussi que vous exécutez le script depuis un shell alors oubliez quand vous ouvrez un nouveau script il est par défaut chez vous.

Essayez ce répertoire pour la taille:

/var/nul/Pensée à Propos de Espaces/Dans un Répertoire/Nom de/Et Voici votre fichier.texte

C'est bon, peu importe comment ou où vous l'exécutez.

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

donc pour le rendre réellement utile voici comment changer le répertoire du script d'exécution:

cd "`dirname ""151910920""`"

L'espoir qui aide

16
répondu 4 revsMike Bethany 2011-02-06 02:04:03

je voudrais utiliser quelque chose comme ceci:

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

# 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
15
répondu Nicolas 2012-11-21 03:57:55

une légère révision à la solution e-satis et 3bcdnlklvc04a souligné dans leur réponse

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

cela devrait encore fonctionner dans tous les cas qu'ils ont énumérés.

EDIT: prévenir popd après l'échec de pushd, grâce à konsolebox

14
répondu Fuwjax 2017-05-23 10:31:38

Voici la manière simple et correcte:

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

explication:

  • ${BASH_SOURCE[0]} - le chemin complet vers le script. La valeur de ceci sera correcte même lorsque le script est source, par exemple source <(echo 'echo "151920920"') imprime bash , alors que le remplacer par ${BASH_SOURCE[0]} affichera le chemin complet du script. (Bien sûr, cela suppose que vous êtes D'accord de prendre une dépendance sur Bash.)

  • readlink -f - résout de façon récursive tout lien symbolique dans le chemin spécifié. Il s'agit d'une extension GNU, et non disponible sur (par exemple) les systèmes BSD. Si vous utilisez un Mac, vous pouvez utiliser Homebrew pour installer GNU coreutils et le remplacer par greadlink -f .

  • et bien sûr dirname obtient le répertoire parent du chemin.

14
répondu James Ko 2016-02-20 07:53:23
#!/bin/sh
PRG=""151900920""

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

scriptdir=`dirname "$PRG"`
12
répondu Monkeyboy 2008-09-13 01:28:47

$_ vaut la peine de mentionner comme une alternative à 0$. Si vous exécutez un script à partir de bash, la réponse acceptée peut être raccourcie à:

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

Notez que ce doit être la première instruction dans votre script.

11
répondu hurrymaplelad 2011-09-16 19:05:51

j'ai comparé plusieurs des réponses données, et trouver des solutions plus compactes. Ceux-ci semblent gérer tous les cas de bord fou qui découlent de votre combinaison préférée de:

  • chemins Absolus ou relatifs chemins
  • Fichier et répertoire de liens souples
  • Invocation comme script , bash script , bash -c script , source script , ou . script
  • espaces, onglets, les retours à la ligne, unicode, etc. dans les répertoires et / ou nom de fichier
  • noms de fichiers commençant par un tiret

si vous utilisez Linux, il semble que l'utilisation de la poignée proc soit la meilleure solution pour localiser la source entièrement résolue du script en cours d'exécution (dans une session interactive, le lien pointe vers le /dev/pts/X respectif):

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

cela a un petit peu de laideur à elle, mais le fix est compact et facile à comprendre. Nous n'utilisons pas seulement des primitives bash, mais je suis d'accord avec cela parce que readlink simplifie considérablement la tâche. Le echo X ajoute un X à la fin de la chaîne de variables de sorte que tout espace de suite dans le nom de fichier ne soit pas mangé, et la substitution de paramètre ${VAR%X} à la fin de la ligne se débarrasse du X . Parce que readlink ajoute une nouvelle ligne de son propre (qui serait normalement mangée dans la commande nous devons nous débarrasser de cela aussi. Ceci est le plus facilement accompli en utilisant le schéma de citation $'' , qui nous permet d'utiliser des séquences d'échappement telles que \n pour représenter newlines (c'est aussi comment vous pouvez facilement faire des répertoires et des fichiers nommés de façon détournée).

ce qui précède devrait couvrir vos besoins pour localiser le script en cours d'exécution sur Linux, mais si vous n'avez pas le système de fichiers proc à votre disposition., ou si vous essayez de trouver le chemin entièrement résolu d'un autre fichier, alors peut-être que vous trouverez le code ci-dessous utile. Ce n'est qu'une légère modification par rapport à la doublure ci-dessus. Si vous jouez avec des répertoires/noms de fichiers étranges, vérifier la sortie avec ls et readlink est instructif, car ls va sortir des chemins "simplifiés", en remplaçant ? pour des choses comme les nouvelles lignes.

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"
10
répondu billyjmc 2015-07-25 19:14:09

pour les systèmes ayant GNU coreutils readlink (eg. linux):

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

Pas besoin d'utiliser BASH_SOURCE quand "151920920" contient le nom du script.

10
répondu user1338062 2018-05-13 04:34:37

essayez d'utiliser:

real=$(realpath $(dirname "151900920"))
8
répondu eeerahul 2012-02-06 11:20:08

So... Je crois que j'ai eu celui-là. En retard à la fête, mais je pense que certains apprécieront d'être ici est-ce qu'ils rencontrent ce fil. Les commentaires devraient expliquer.

#!/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 ""151900920""
## specificies that the "151900920" 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 ""151900920"".

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

# Yay ANSI l33t codes! Fancy.
 printf "\n3[3mfrom/as: 3[4m"151900920"3[0m\n\n3[1mUSAGE:3[0m   "
 printf "3[4m$scriptname3[24m [ link | file | dir ]\n\n         "
 printf "Recursive readlink for the authoritative file, symlink after "
 printf "symlink.\n\n\n         3[4m$scriptname3[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
8
répondu Geoff Nixon 2013-12-21 17:47:37

Hmm, si dans le chemin basename & dirname ne vont tout simplement pas le couper et marcher sur le chemin est difficile (et si parent n'exportait pas PATH!). Cependant, le shell doit avoir une poignée ouverte à son script, et bash la poignée est # 255.

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

ça me va.

7
répondu Joshua 2011-07-27 20:17:03

essayer la solution cross-compatible suivante:

CWD="$(cd -P -- "$(dirname -- ""151900920"")" && pwd -P)"
Les commandes

comme realpath ou readlink ne sont pas toujours disponibles (selon le système d'exploitation) et ${BASH_SOURCE[0]} n'est disponible qu'en shell bash.

alternativement vous pouvez essayer la fonction suivante dans bash:

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

cette fonction prend 1 argument. Si l'argument a déjà le chemin absolu, imprimez-le tel quel, sinon Imprimez $PWD variable + argument de nom de fichier (sans préfixe ./ ).

Related:

7
répondu kenorb 2015-04-24 02:23:02

cela fonctionne à bash-3.2:

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

voici un exemple de son usage:

dites que vous avez un ~/bin répertoire, qui est dans votre $PATH . Vous avez script A dans ce répertoire. It source s script ~ / bin/lib / B . Vous savez où le script inclus est relatif à l'original (le sous-répertoire lib ), mais pas là où il est relatif au répertoire courant de l'utilisateur.

ceci est résolu par ce qui suit (à l'intérieur de A ):

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

peu importe où se trouve l'utilisateur ou comment il appelle le script, cela marchera toujours.

6
répondu Matt Tardiff 2010-09-03 06:44:30

C'est le seul moyen que j'ai trouvé pour dire de façon fiable:

SCRIPT_DIR=$(dirname $(cd "$(dirname "$BASH_SOURCE")"; pwd))
6
répondu BillTorpey 2015-01-13 12:54:18

aucun de ceux - ci n'a fonctionné pour un script bash lancé par Finder dans OS X-j'ai fini par utiliser:

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

pas joli, mais ça fait le boulot.

5
répondu tigfox 2013-02-14 17:23:28

la meilleure solution compacte à mon avis serait:

"$( cd "$( echo "${BASH_SOURCE[0]%/*}" )"; pwd )"

il n'y a pas de dépendance autre que Bash. L'utilisation de dirname , readlink et basename entraînera éventuellement des problèmes de compatibilité, de sorte qu'il est préférable de les éviter si possible.

5
répondu AsymLabs 2013-10-08 14:24:13