Obtenez le répertoire source d'un script Bash à partir du script lui-même

StackOverflow https://stackoverflow.com/questions/59895

  •  09-06-2019
  •  | 
  •  

Question

Comment obtenir le chemin du répertoire dans lequel un Frapper le script est localisé, à l'intérieur ce scénario ?

Par exemple, disons que je souhaite utiliser un script Bash comme lanceur pour une autre application.Je souhaite remplacer le répertoire de travail par celui où se trouve le script Bash, afin de pouvoir opérer sur les fichiers de ce répertoire, comme ceci :

$ ./application
Était-ce utile?

La solution

#!/bin/bash

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

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

Cela fonctionnera tant que le dernier composant du chemin utilisé pour trouver le script n'est pas un lien symbolique (les liens vers les répertoires sont OK).Si vous souhaitez également résoudre les liens vers le script lui-même, vous avez besoin d'une solution multiligne :

#!/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 )"

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

Méfiez-vous:si tu cd dans un autre répertoire avant d'exécuter cet extrait, le résultat peut être incorrect !

Faites également attention à $CDPATH pièges, et les effets secondaires de sortie stderr si l'utilisateur a intelligemment remplacé cd pour rediriger la sortie vers stderr à la place (y compris les séquences d'échappement, comme lors de l'appel update_terminal_cwd >&2 sur Mac).Ajouter >/dev/null 2>&1 à la fin de votre cd la commande prendra en charge les deux possibilités.

Pour comprendre comment cela fonctionne, essayez d'exécuter cette forme plus détaillée :

#!/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'"

Et il affichera 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'

Autres conseils

Utiliser dirname "$0":

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

en utilisant pwd seul ne fonctionnera pas si vous n'exécutez pas le script à partir du répertoire dans lequel il se trouve.

[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

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

dirname "$0"

Mais, comme mat b souligné, le chemin renvoyé est différent selon la manière dont le script est appelé.pwd ne fait pas le travail car cela vous indique uniquement quel est le répertoire actuel, pas dans quel répertoire réside le script.De plus, si un lien symbolique vers un script est exécuté, vous obtiendrez un chemin (probablement relatif) vers l'endroit où réside le lien, et non le script réel.

D'autres ont mentionné le lire le lien commande, mais dans sa forme la plus simple, vous pouvez utiliser :

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

readlink résoudra le chemin du script en 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 en un chemin complet.

Voici un script démontrant chacun de ces éléments, quelrép.sh :

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

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

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

Encore une fois, mais en utilisant le chemin complet du script :

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

Changement de répertoire maintenant :

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

Et enfin en utilisant un lien symbolique pour exécuter le script :

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

Fonctionne pour toutes les versions, y compris

  • lorsqu'il est appelé via un lien logiciel à plusieurs profondeurs,
  • quand le fichier
  • lorsque le script est appelé par commande "source" alias . (point) opérateur.
  • quand argument $0 est modifié à partir 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 lien symbolique relatif toi vouloir pour le suivre et renvoyer 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é sous forme de chemin complet, quel que soit son nom.
Assurez-vous simplement de le localiser au début du script.

Ce commentaire et ce code Copyleft, licence sélectionnable sous GPL2.0 ou version ultérieure ou CC-SA 3.0 (CreativeCommons Share Alike) ou version ultérieure.c) 2008.Tous droits réservés.Aucune garantie d'aucune sorte.Tu étais prévenu.
http://www.gnu.org/licenses/gpl-2.0.txt
http://creativecommons.org/licenses/by-sa/3.0/
18eedfe1c99df68dc94d4a94712a71aaa8e1e9e36cacf421b9463dd2bbaa02906d0d6656

Réponse courte:

`dirname $0`

ou (de préférence):

$(dirname "$0")

Vous pouvez utiliser $BASH_SOURCE

#!/bin/bash

scriptdir=`dirname "$BASH_SOURCE"`

Notez que vous devez utiliser #!/bin/bash et non #!/bin/sh puisque c'est une extension bash

Cela devrait le faire :

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

Fonctionne avec des liens symboliques et des espaces dans le chemin.Voir les pages de manuel pour nom de répertoire et lire le lien.

Modifier:

D'après la piste des commentaires, il semble que cela ne fonctionne pas avec Mac OS.Je n'ai pas d'idées pourquoi c'est comme ça.Aucune suggestion?

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

Cependant, dirname donne précisément la partie répertoire du nom de fichier, qui sera très probablement relative au répertoire de travail actuel.Si votre script doit changer de répertoire pour une raison quelconque, la sortie de dirname devient dénué de sens.

Je suggère ce qui suit :

#!/bin/bash

reldir=`dirname $0`
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 bash distincte, il n'est pas nécessaire de restaurer le répertoire de travail par la suite, mais si vous souhaitez modifier votre script pour une raison quelconque, vous pouvez facilement attribuer la valeur de pwd à une variable avant de changer de répertoire, pour une utilisation future.

Bien que juste

cd `dirname $0`

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

Je ne pense pas que ce soit aussi facile que d’autres l’ont prétendu.pwd ne fonctionne pas, car le répertoire actuel n'est pas nécessairement le répertoire contenant le script.$0 n'a pas toujours l'information non plus.Considérez les trois manières suivantes d’appeler un script.

./script

/usr/bin/script

script

Dans les première et troisième manières, $0 n'a pas les informations de chemin complètes.Dans les deuxième et troisième, pwd ne fonctionne pas.La seule façon d'obtenir le répertoire de la troisième manière serait de parcourir le chemin et de trouver le fichier avec la correspondance correcte.Fondamentalement, le code devrait refaire ce que fait le système d'exploitation.

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

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

Cela obtient le répertoire de travail actuel sur Mac OS X 10.6.6 :

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

Je suis fatigué de revenir encore et encore sur cette page pour copier-coller la réponse acceptée.Le problème, c’est que ce n’est pas facile à comprendre et à retenir.

Voici un script facile à retenir :

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

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

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

Voici un one-liner conforme à POSIX :

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

# test
echo $SCRIPT_PATH

J'ai essayé chacun d'eux et aucun d'entre eux n'a fonctionné.L'un d'entre eux était très proche mais avait un petit bug qui le cassait gravement ;ils ont oublié de mettre le chemin entre guillemets.

De plus, beaucoup de gens supposent que vous exécutez le script à partir d'un shell, alors oubliez que lorsque vous ouvrez un nouveau script, il est par défaut celui de votre domicile.

Essayez ce répertoire pour la taille :

/var/Personne/Pensée/À propos des espaces/Dans un répertoire/Nom/Et voici votre fichier.text

Cela fonctionne correctement, peu importe comment ou où vous l'exécutez.

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

Donc, pour le rendre réellement utile, voici comment accéder au répertoire du script en cours d'exécution :

cd "`dirname "$0"`"

J'espère que cela pourra aider

Voici la méthode simple et correcte :

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

Explication:

  • ${BASH_SOURCE[0]} - le chemin complet du script.La valeur de ceci sera correcte même lorsque le script est source, par ex. source <(echo 'echo $0') impressions frapper, en le remplaçant par ${BASH_SOURCE[0]} imprimera le chemin complet du script.(Bien sûr, cela suppose que vous acceptez de dépendre de Bash.)

  • readlink -f - Résout de manière récursive tous les liens symboliques 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 remplacez cela par greadlink -f.

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

J'utiliserais quelque chose comme ceci :

# 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

Une légère révision de la solution e-satis et 3bcdnlklvc04a signalée dans leur réponse

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

Cela devrait toujours fonctionner dans tous les cas répertoriés.

MODIFIER:empêcher popd après l'échec de pushd, grâce à konsolebox

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

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

scriptdir=`dirname "$PRG"`

$_ vaut la peine d'être mentionné comme alternative à 0 $.Si vous exécutez un script depuis bash, la réponse acceptée peut être raccourcie à :

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

Notez que cela doit être la première instruction de votre script.

J'ai comparé de nombreuses réponses données et proposé des solutions plus compactes.Ceux-ci semblent gérer tous les cas extrêmes qui découlent de votre combinaison préférée de :

  • Chemins absolus ou chemins relatifs
  • Liens logiciels vers des fichiers et des répertoires
  • Invocation comme script, bash script, bash -c script, source script, ou . script
  • Espaces, tabulations, nouvelles lignes, Unicode, etc.dans les répertoires et/ou le nom de fichier
  • Noms de fichiers commençant par un trait d'union

Si vous utilisez Linux, il semble que l'utilisation du proc handle est 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):

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

Cela a un peu de laideur, mais le correctif est compact et facile à comprendre.Nous n'utilisons pas uniquement les primitives bash, mais cela me convient car readlink simplifie considérablement la tâche.Le echo X ajoute un X à la fin de la chaîne variable afin que tout espace de fin dans le nom de fichier ne soit pas mangé, et la substitution du paramètre ${VAR%X} au bout de la ligne se débarrasse du X.Parce que readlink ajoute sa propre nouvelle ligne (qui serait normalement consommée lors de la substitution de commande sans notre astuce précédente), nous devons également nous en débarrasser.Ceci est réalisé plus facilement en utilisant le $'' schéma de citation, qui nous permet d'utiliser des séquences d'échappement telles que \n pour représenter les nouvelles lignes (c'est aussi ainsi que vous pouvez facilement créer des répertoires et des fichiers aux noms sournois).

Ce qui précède devrait couvrir vos besoins pour localiser le script en cours d'exécution sous Linux, mais si vous n'avez pas le proc système de fichiers à votre disposition, ou si vous essayez de localiser le chemin entièrement résolu d'un autre fichier, le code ci-dessous vous sera peut-être utile.Ce n'est qu'une légère modification par rapport au one-liner ci-dessus.Si vous jouez avec des noms de répertoires/fichiers étranges, vérifiez la sortie avec les deux ls et readlink est informatif, car ls affichera des chemins "simplifiés", en les 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"

Essayez d'utiliser :

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

Pour les systèmes ayant GNU coreutils readlink (par ex.Linux) :

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

Pas besoin d'utiliser BASH_SOURCE quand $0 contient le nom du fichier de script.

Donc...Je crois que j'ai celui-ci.Il est tard pour la fête, mais je pense que certains apprécieront d'être ici s'ils tombent sur ce fil.Les commentaires doivent 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 "$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

Essayez la solution de compatibilité croisée suivante :

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

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

Alternativement, vous pouvez essayer la fonction suivante dans bash :

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

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

En rapport:

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

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

travaille pour moi.

Pour résumer de nombreuses réponses :

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

Commandes utilisées

    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`

Le résultat:

     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

Voirhttps://pastebin.com/J8KjxrPF

Cela fonctionne dans bash-3.2 :

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

Voici un exemple de son utilisation :

Dis que tu as un ~/poubelle répertoire, qui se trouve dans votre $CHEMIN.Vous avez un script UN à l'intérieur de ce répertoire.Il sourcele scénario ~/bin/lib/B.Vous savez où se trouve le script inclus par rapport à celui d'origine (le sous-répertoire lib), mais pas par rapport au répertoire actuel de l'utilisateur.

Ceci est résolu par ce qui suit (à l'intérieur UN):

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

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

Aucun de ces éléments n'a fonctionné pour un script bash lancé par le Finder sous 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 il fait le travail.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top