Fondamentalement, j'ai besoin d'exécuter le script avec des chemins d'accès liés à l'emplacement du fichier de script shell, comment puis-je changer le répertoire actuel dans le même répertoire que celui où réside le fichier de script?
511
Réponses:
Dans Bash, vous devriez obtenir ce dont vous avez besoin comme ceci:
la source
readlink
(voir la réponse de al ci-dessous)$BASH_SOURCE
à la place de$0
, car$0
il ne contient pas toujours le chemin du script invoqué, comme lors de la «sourcing» d'un script.$BASH_SOURCE
est spécifique à Bash, la question concerne le script shell en général.CUR_PATH=$(pwd)
oupwd
renvoyez le répertoire courant (qui ne doit pas nécessairement être le répertoire parent des scripts)!$BASH_SOURCE
, et elle renvoie ce dont j'avais besoin. Mon script est appelé à partir d'un autre script et$0
renvoie.
alors que$BASH_SOURCE
renvoie le sous-répertoire de droite (dans mon casscripts
).Le message d'origine contient la solution (ignorez les réponses, elles n'ajoutent rien d'utile). Le travail intéressant est effectué par la commande unix mentionnée
readlink
avec option-f
. Fonctionne lorsque le script est appelé par un chemin absolu ainsi que par un chemin relatif.Pour bash, sh, ksh:
Pour tcsh, csh:
Voir aussi: https://stackoverflow.com/a/246128/59087
la source
readlink
. C'est pourquoi j'ai recommandé d'utiliser pushd / popd (intégrés pour bash).-f
option de fairereadlink
quelque chose de différent sur OS X (Lion) et éventuellement BSD. stackoverflow.com/questions/1055671/…-f
n'est pas du tout pris en charge sur OS X (comme pour Lion); là, vous pouvez soit supprimer le-f
pour faire avec la résolution d'au plus un niveau d'indirection, par exemplepushd "$(dirname "$(readlink "$BASH_SOURCE" || echo "$BASH_SOURCE")")"
, ou vous pouvez rouler votre propre script de suivi de lien symbolique récursif comme illustré dans la publication liée.sh /some/other/directory/script.sh)
, dans ce cas, ce.
serait votre pwd, pas/some/other/directory
Un commentaire antérieur sur une réponse le disait, mais il est facile de manquer parmi toutes les autres réponses.
Lors de l'utilisation de bash:
Manuel de référence Bash, 5.2 Variables Bash
la source
dirname "$BASH_SOURCE"
place pour gérer les espaces dans $ BASH_SOURCE."$(dirname "${BASH_SOURCE[0]}")"
En supposant que vous utilisez bash
Ce script doit imprimer le répertoire dans lequel vous vous trouvez, puis le répertoire dans lequel se trouve le script. Par exemple, lorsque vous l'appelez depuis
/
avec le script dans/home/mez/
, il génèreN'oubliez pas que lorsque vous affectez des variables à la sortie d'une commande, encapsulez la commande dans
$(
et)
- ou vous n'obtiendrez pas la sortie souhaitée.la source
Si vous utilisez bash ....
la source
pushd
/popd
parcd $(dirname "${0}")
etcd -
le faire fonctionner sur d'autres shells, s'ils ont unpwd -L
.Comme le suggère le Marko:
Cela fonctionne à moins que vous n'exécutiez le script à partir du même répertoire où le script réside, auquel cas vous obtenez une valeur de '.'
Pour contourner ce problème, utilisez:
Vous pouvez désormais utiliser la variable current_dir tout au long de votre script pour faire référence au répertoire de script. Cependant, cela peut toujours avoir le problème du lien symbolique.
la source
La meilleure réponse à cette question a été trouvée ici:
Obtenir le répertoire source d'un script Bash de l'intérieur
Et c'est:
One-liner qui vous donnera le nom de répertoire complet du script, peu importe d'où il est appelé.
Pour comprendre comment cela fonctionne, vous pouvez exécuter le script suivant:
la source
la source
Faisons-en un oneliner POSIX:
Testé sur de nombreux shells compatibles Bourne, y compris ceux BSD.
Pour autant que je sache, je suis l'auteur et je l'ai mis dans le domaine public. Pour plus d'informations, voir: https://www.jasan.tk/posts/2017-05-11-posix_shell_dirname_replacement/
la source
cd: too many arguments
si des espaces dans le chemin d'accès, et retourne$PWD
. (une solution évidente, mais montre juste combien de cas de bord il y a réellement)la source
Si vous souhaitez obtenir le répertoire de script réel (que vous appeliez le script à l'aide d'un lien symbolique ou directement), essayez:
Cela fonctionne à la fois sur linux et macOS. Je ne pouvais voir personne parler ici
realpath
. Je ne sais pas s'il y a des inconvénients dans cette approche.sur macOS, vous devez installer
coreutils
pour utiliserrealpath
. Par exemple:brew install coreutils
.la source
INTRODUCTION
Cette réponse corrige la réponse très brisée mais choquante de ce fil (écrite par TheMarko):
POURQUOI L'UTILISATION de dirname "$ 0" SUR SON PROPRE NE FONCTIONNE PAS?
dirname $ 0 ne fonctionnera que si l'utilisateur lance le script d'une manière très spécifique. J'ai pu trouver plusieurs situations où cette réponse échoue et bloque le script.
Tout d'abord, comprenons comment cette réponse fonctionne. Il obtient le répertoire de script en faisant
$ 0 représente la première partie de la commande appelant le script (c'est essentiellement la commande entrée sans les arguments:
$ 0 = "/ certains / chemin /./ script"
dirname trouve essentiellement le dernier / dans une chaîne et le tronque là. Donc si vous le faites:
vous obtiendrez: / usr / bin
Cet exemple fonctionne bien car / usr / bin / sha256sum est un chemin correctement formaté mais
ne fonctionnerait pas bien et vous donnerait:
Disons que vous êtes dans le même répertoire que votre script et que vous le lancez avec cette commande
0 $ dans cette situation sera ./script et dirname $ 0 donnera:
En utilisant:
Sans entrer le chemin complet donnera également un BASEDIR = "."
Utilisation de répertoires relatifs:
Donne un nom de répertoire $ 0 de:
Si vous êtes dans le répertoire / some et que vous appelez le script de cette manière (notez l'absence de / au début, encore une fois un chemin relatif):
Vous obtiendrez cette valeur pour dirname $ 0:
et ./path/./script (une autre forme du chemin relatif) donne:
Les deux seules situations où basedir $ 0 fonctionnera sont si l'utilisateur utilise sh ou touch pour lancer un script car les deux donneront $ 0:
qui vous donnera un chemin que vous pouvez utiliser avec dirname.
LA SOLUTION
Vous devez prendre en compte et détecter chacune des situations mentionnées ci-dessus et appliquer un correctif si cela se produit:
la source
Ce one-liner indique où se trouve le script shell, peu importe si vous l'avez exécuté ou si vous l'avez obtenu . En outre, il résout tous les liens symboliques impliqués, si tel est le cas:
Au fait, je suppose que vous utilisez / bin / bash .
la source
Autant de réponses, toutes plausibles, chacune avec des avantages et des inconvénients et des objectifs légèrement différents (qui devraient probablement être énoncés pour chacun). Voici une autre solution qui répond à un objectif principal à la fois d'être clair et de fonctionner sur tous les systèmes, sur tous les bash (pas d'hypothèses sur les versions de bash
readlink
ou lespwd
options), et fait raisonnablement ce que vous attendez (par exemple, la résolution de liens symboliques est un problème intéressant, mais ce n'est généralement pas ce que vous voulez réellement), gérez les cas marginaux comme les espaces dans les chemins, etc., ignore les erreurs et utilise une valeur par défaut saine s'il y a des problèmes.Chaque composant est stocké dans une variable distincte que vous pouvez utiliser individuellement:
la source
Inspiré par la réponse de Blueyed
la source
Cela devrait faire l'affaire:
Cela peut sembler laid selon la façon dont il a été invoqué et le cwd, mais devrait vous amener là où vous devez aller (ou vous pouvez modifier la chaîne si vous vous souciez de son apparence).
la source
`pwd`/`dirname $0`
mais peut toujours échouer sur les liens symboliques