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"?

Talespin_Kit
la source

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.

paxdiablo
la source
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

Emmanuel Devaux
la source
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
jerblack
la source
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
Tahsin Turkoz
la source
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
Eurospoofer
la source
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
kmchen
la source
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
alper
la source
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.

aerijman
la source