4860 votes

Peut un script Bash dire ce répertoire, il est stocké dans?

Comment puis-je obtenir le chemin d'accès du répertoire dans lequel un Bash script est situé à PARTIR de ce script Bash?

Par exemple, disons que je veux utiliser un script Bash comme un lanceur d'applications pour une autre application. Je veux changer le répertoire de travail de celui où le script Bash est situé, de sorte que je peux fonctionner sur les fichiers dans ce répertoire, comme suit:

$ ./application

6443voto

dogbane Points 85749
DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"

Est utile, one-liner qui va vous donner le nom complet du répertoire du script, peu importe où il est appelé à partir d'

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

SOURCE="${BASH_SOURCE[0]}"
while [ -h "$SOURCE" ]; do # resolve $SOURCE until the file is no longer a symlink
  DIR="$( cd -P "$( dirname "$SOURCE" )" && 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" )" && pwd )"

Ce dernier fonctionne 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 l'exécution de ce fragment de code, le résultat peut être incorrecte! Aussi, surveillez $CDPATH de pièges.

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

#!/bin/bash

SOURCE="${BASH_SOURCE[0]}"
while [ -h "$SOURCE" ]; do # resolve $SOURCE until the file is no longer a symlink
  TARGET="$(readlink "$SOURCE")"
  if [[ $SOURCE == /* ]]; 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 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'

860voto

matt b Points 73770

Utiliser dirname:

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

à l'aide de pwd seul ne fonctionnera pas si vous n'êtes pas exécuter le script dans le répertoire, 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

505voto

phatblat Points 2046

Le dirname de commande est le plus simple, il suffit de l'analyse du chemin pour le nom de fichier hors de la $0 (nom du script) de la variable:

dirname "$0"

Mais, comme matt b a souligné, le chemin retourné est différent selon la façon dont le script est appelé. pwd ne pas faire le travail parce que ne vous raconte pas ce que le répertoire courant est, pas ce répertoire que le script réside dans. En outre, si un lien symbolique vers un script est exécuté, vous allez avoir un (probablement relative) chemin d'accès où le lien réside, non pas le script.

D'autres ont mentionné la readlink de commande, mais c'est plus simple, vous pouvez utiliser:

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

readlink permettra de résoudre le script chemin d'accès à un chemin absolu de la racine du système de fichiers. Ainsi, tous les chemins contenant des simple ou double de points, les tildes et/ou des liens symboliques seront résolus d'un chemin d'accès complet.

Voici un script démontrant chacun de ces, 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))"

L'exécution de ce script dans mon répertoire home, 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

Maintenant modifier les répertoires:

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

Et, enfin, à l'aide d'un lien symbolique afin d'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

182voto

user25866 Points 301
SCRIPT_PATH="${BASH_SOURCE[0]}";
if ([ -h "${SCRIPT_PATH}" ]) then
  while([ -h "${SCRIPT_PATH}" ]) do SCRIPT_PATH=`readlink "${SCRIPT_PATH}"`; done
fi
pushd . > /dev/null
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,
  • lorsque le fichier il
  • lorsque le script appelé par la commande "source" aka . (dot) de l'opérateur.
  • lorsque arg $0 est modifié de l'appelant.
  • "./de script"
  • "/full/chemin/vers/le / script"
  • "//chemin/../../autre/chemin/script"
  • "./certains/dossier/script"

Par ailleurs, si le script bash lui-même est un lien symbolique par rapport que vous souhaitez suivre et retour le chemin d'accès complet de la liés à de script:

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ée dans le chemin d'accès complet, peu importe comment il s'appelle.
Assurez-vous de localiser ce au début du script.

Ce commentaire et le code Copyleft, le choix de la licence en vertu de la GPL2.0 ou plus tard ou CC-SA 3.0 (CreativeCommons Partage à l'identique) 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/
18eedfe1c99df68dc94d4a94712a71aaa8e1e9e36cacf421b9463dd2bbaa02906d0d6656

103voto

Mr Shark Points 5241

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

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X