Obtenir le chemin du répertoire de fichiers à partir du chemin de fichier


400

Dans Bash, si VAR="/home/me/mydir/file.c", comment puis-je obtenir "/home/me/mydir"?

Réponses:


649

dirnameet basenamesont les outils que vous recherchez pour extraire des composants de chemin:

$ VAR=/home/me/mydir/file.c

$ DIR=$(dirname "${VAR}")

$ echo "${DIR}"
/home/me/mydir

$ basename "${VAR}"
file.c

Ils ne sont pas internes commandes Bash mais ils font partie de la norme POSIX (voir dirname, basename) et devrait donc être disponible sur la grande majorité des systèmes qui seront en cours d' exécution Bash.


4
Pourquoi utiliser des crochets autour des noms de variables, et non pas "$ VAR" par exemple?
user658182

1
stackoverflow.com/questions/8748831/… répond à la question ci-dessus.
user658182

1
@ user658182 Dans cet exemple particulier, cela se fait par habitude, pas par nécessité.
Panier abandonné

95
$ export VAR=/home/me/mydir/file.c
$ export DIR=${VAR%/*}
$ echo "${DIR}"
/home/me/mydir

$ echo "${VAR##*/}"
file.c

Pour éviter la dépendance avec basenameetdirname


3
Étant donné que les deux font partie de POSIX, une dépendance ne devrait pas être un problème.
orkoden

1
orkoden, vous avez raison. Le but de ma réponse est de montrer qu'il n'y a aucune obligation d'exécuter deux processus supplémentaires. bash est autosuffisant pour le cas d'utilisation.
Emmanuel Devaux

2
J'utilise la méthode d'Emmanuel parce que je souhaite transmettre un nom de fichier ou de dossier, puis calculer le chemin du dossier. L'utilisation de cette expression régulière fait la bonne chose, tandis que la fonction dirname a renvoyé le dossier parent lorsque j'entre un dossier.
AnneTheAgile

8
Cependant, s'il n'y a pas d'informations de chemin dans $ VAR, $ {VAR% / *} / test produit une valeur inattendue égale à $ VAR / test tandis que $ (dirname $ VAR) produira la valeur plus prévisible et appropriée de ./test. C'est un gros problème car le premier tentera de traiter le nom de fichier comme un répertoire tandis que le second sera OK.
davemyron

19

Sur une note connexe, si vous n'avez que le nom de fichier ou le chemin d'accès relatif, dirnamecela ne sera pas utile en soi. Pour moi, la réponse a fini par être readlink.

fname='txtfile'    
echo $(dirname "$fname")                # output: .
echo $(readlink -f "$fname")            # output: /home/me/work/txtfile

Vous pouvez ensuite combiner les deux pour obtenir uniquement le répertoire.

echo $(dirname $(readlink -f "$fname")) # output: /home/me/work

1
si plusieurs composants de chemin d'accès n'existaient pas, vous devriez utiliser readlink -m "$fname"pour
canoniser le

7

Si vous vous souciez des fichiers cibles pour être un lien symbolique, vous pouvez d'abord le vérifier et obtenir le fichier d'origine. La clause if ci-dessous peut vous aider.

if [ -h $file ]
then
 base=$(dirname $(readlink $file))
else
 base=$(dirname $file)
fi

5

Je jouais avec ça et j'ai trouvé une alternative.

$ VAR=/home/me/mydir/file.c

$ DIR=`echo $VAR |xargs dirname`

$ echo $DIR
/home/me/mydir

La partie que j'ai aimé, c'est qu'il était facile d'étendre la sauvegarde de l'arborescence:

$ DIR=`echo $VAR |xargs dirname |xargs dirname |xargs dirname`

$ echo $DIR
/home

1

Voici un script que j'ai utilisé pour le rognage récursif. Remplacez $ 1 par le répertoire que vous voulez, bien sûr.

BASEDIR="$1"
IFS=$'\n'
cd $BASEDIR
 for f in $(find . -type f -name ' *')
 do 
    DIR=$(dirname "$f")
    DIR=${DIR:1}
    cd $BASEDIR$DIR
    rename 's/^ *//' *
 done

0

Tout d'abord, je l'ai remplacé /par un espace vide ( ). Ensuite, j'ai supprimé tous les caractères avant tout espace vide ( ). À la fin, j'ai supprimé le premier caractère qui est un espace vide ( ).

$ VAR="/home/me/mydir/file.c"

$ echo $VAR | tr '/' ' ' | sed 's/^.* / /' | cut -c2-
file.c

0
HERE=$(cd $(dirname $BASH_SOURCE) && pwd)

où vous obtenez le chemin complet avec new_path = $(dirname ${BASH_SOURCE[0]}). Vous modifiez le répertoire en cours avec cd new_path , puis exécutez pwdpour obtenir le chemin d'accès complet au répertoire en cours.

En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.