316 votes

Obtenir le parent d'un répertoire en Bash

Si j'ai un chemin de fichier tel que...

/home/smith/Desktop/Test
/home/smith/Desktop/Test/

Comment changer la chaîne de caractères pour que ce soit le répertoire parent ?

par exemple

/home/smith/Desktop
/home/smith/Desktop/

4 votes

Vous pouvez simplement utiliser ' .. mais ce n'est peut-être pas ce que vous aviez à l'esprit.

2 votes

' ne peut être utilisé que pour le chemin d'un répertoire et non pour le chemin d'un fichier.

493voto

Michael Hoffman Points 8557
dir=/home/smith/Desktop/Test
parentdir="$(dirname "$dir")"

Cela fonctionne également s'il y a une barre oblique de fin.

22 votes

Les guillemets à l'intérieur sont importants ou vous allez perdre toutes vos données.

20 votes

Et la variante que j'utilise pour obtenir le parent du répertoire de travail actuel : parentdir=$(dirname `pwd`)

0 votes

Le parent du répertoire de travail actuel est simplement .. .

39voto

Riaz Rizvi Points 774

Il est clair que le répertoire parent est donné en ajoutant simplement le nom de fichier en points :

/home/smith/Desktop/Test/..     # unresolved path

Mais vous devez vouloir le résolu (un chemin absolu sans aucun composant de chemin en pointillés) :

/home/smith/Desktop             # resolved path

Le problème avec les meilleures réponses qui utilisent dirname est qu'ils ne fonctionnent pas lorsque vous entrez dans un chemin avec des points :

$ dir=~/Library/../Desktop/../..
$ parentdir="$(dirname "$dir")"
$ echo $parentdir
/Users/username/Library/../Desktop/..   # not fully resolved

C'est plus puissant :

dir=/home/smith/Desktop/Test
parentdir=$(builtin cd $dir; pwd)

Vous pouvez le nourrir /home/smith/Desktop/Test/.. mais aussi des chemins plus complexes comme :

$ dir=~/Library/../Desktop/../..
$ parentdir=$(builtin cd $dir; pwd)
$ echo $parentdir
/Users                                  # the fully resolved path!

REMARQUE : l'utilisation de builtin garantit qu'aucune variante de fonction définie par l'utilisateur de cd est appelé, mais plutôt le formulaire utilitaire par défaut qui n'a pas de sortie.

0 votes

Utilisation de eval n'est PAS génial s'il y a la moindre chance d'analyser l'entrée de l'utilisateur qui pourrait vous mettre dans un endroit où vous ne vous y attendez pas ou exécuter de mauvaises choses contre votre système. Pouvez-vous utiliser pushd $dir 2>&1 >/dev/null && pwd && popd 2>&1 >/dev/null au lieu de la eval ?

3 votes

Vous n'avez pas besoin eval du tout : faites simplement parentdir=$(cd -- "$dir" && pwd) . Puisque le cd est exécuté dans un sous-shell, vous n'avez pas besoin de cd à l'endroit où nous étions. Le site -- est ici au cas où l'expansion de $dir commence par un trait d'union. Le site && est juste pour éviter parentdir pour avoir un contenu non vide lorsque le cd n'a pas réussi.

0 votes

@gniourf_gniourf merci. J'ai mis à jour la réponse en fonction de vos conseils.

35voto

Endu A-d Points 181

Il suffit d'utiliser echo $(cd ../ && pwd) tout en travaillant dans le répertoire dont vous voulez connaître le répertoire parent. Cette chaîne a également l'avantage de ne pas avoir de slashs de fin.

1 votes

Vous n'avez pas besoin echo ici.

21voto

Andreas Spindler Points 1612

...mais ce qui est "vu aquí "est cassé. Voici la solution :

> pwd
/home/me
> x='Om Namah Shivaya'
> mkdir "$x" && cd "$x"
/home/me/Om Namah Shivaya
> parentdir="$(dirname "$(pwd)")"
> echo $parentdir
/home/me

18voto

Motivation pour une autre réponse

J'aime les codes très courts, clairs et garantis. Point bonus s'il n'exécute pas de programme externe, car le jour où vous devrez traiter un grand nombre d'entrées, il sera nettement plus rapide.

Principe

Je ne suis pas sûr des garanties que vous avez et que vous voulez, alors je vous les offre quand même.

Si vous avez des garanties, vous pouvez le faire avec un code très court. L'idée est d'utiliser la fonction de substitution de texte de bash pour couper le dernier slash et tout ce qui suit.

Répondez à la question initiale en allant des cas simples aux cas plus complexes.

Si le chemin est garanti se terminer sans aucun slash (in et out)

P=/home/smith/Desktop/Test ; echo "${P%/*}"
/home/smith/Desktop

Si le chemin est garanti se terminer par exactement un slash (in et out)

P=/home/smith/Desktop/Test/ ; echo "${P%/*/}/"
/home/smith/Desktop/

Si le chemin d'entrée peut se terminer par zéro ou un slash (pas plus) et que vous voulez que le chemin de sortie se termine sans slash

for P in \
    /home/smith/Desktop/Test \
    /home/smith/Desktop/Test/
do
    P_ENDNOSLASH="${P%/}" ; echo "${P_ENDNOSLASH%/*}"
done

/home/smith/Desktop
/home/smith/Desktop

Si le chemin d'entrée peut avoir beaucoup de slashs étrangers et que vous voulez que le chemin de sortie se termine sans slashs

for P in \
    /home/smith/Desktop/Test \
    /home/smith/Desktop/Test/ \
    /home/smith///Desktop////Test// 
do
    P_NODUPSLASH="${P//\/*(\/)/\/}"
    P_ENDNOSLASH="${P_NODUPSLASH%%/}"
    echo "${P_ENDNOSLASH%/*}";   
done

/home/smith/Desktop
/home/smith/Desktop
/home/smith/Desktop

1 votes

Réponse fantastique. Puisqu'il semble qu'il cherchait un moyen de faire cela à partir d'un script (trouver le répertoire actuel du script et son parent et faire quelque chose relativement à l'endroit où vit le script), c'est une excellente réponse et vous pouvez avoir encore plus de contrôle sur le fait que l'entrée a un slash de fin ou non en utilisant l'expansion des paramètres contre ${BASH_SOURCE[0]} qui serait le chemin complet vers le script s'il n'était pas sourcé via source o . .

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