Obtenir le parent d'un répertoire dans Bash
Si j'ai un chemin de fichier comme...
/home/smith/Desktop/Test
/home/smith/Desktop/Test/
Comment changer la chaîne de caractères pour qu'elle soit le répertoire parent?
p.ex.
/home/smith/Desktop
/home/smith/Desktop/
10 réponses
dir=/home/smith/Desktop/Test
parentdir="$(dirname "$dir")"
fonctionne s'il ya une barre oblique arrière, aussi.
...mais ce qui est "vu ici " 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
il est clair que le répertoire parent est donné en ajoutant simplement le nom du fichier dot-dot:
/home/smith/Desktop/Test/.. # unresolved path
mais vous devez vouloir le résolu chemin (un chemin absolu sans aucun élément de chemin à points):
/home/smith/Desktop # resolved path
le problème avec les réponses du haut qui utilisent dirname
, c'est qu'elles ne fonctionnent pas quand vous entrez 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=`eval "cd $dir;pwd;cd - > /dev/null"`
vous pouvez l'alimenter /home/smith/Desktop/Test/..
, mais aussi des chemins plus complexes comme:
$ dir=~/Library/../Desktop/../..
$ parentdir=`eval "cd $dir;pwd;cd - > /dev/null"`
$ echo $parentdir
/Users # the fully resolved path!
il suffit d'utiliser echo $(cd ../ && pwd)
en travaillant dans le répertoire dont vous voulez connaître le dir parent. Cette chaîne a également l'avantage supplémentaire de ne pas avoir de slashes traînants.
selon que vous avez besoin de chemins absolus, vous pouvez prendre un pas supplémentaire:
child='/home/smith/Desktop/Test/'
parent=$(dirname "$child")
abs_parent=$(realpath "$parent")
Motivation pour une autre réponse
j'aime le code très court, clair et garanti. Bonus point s'il n'exécute pas de programme externe, car le jour où vous devez traiter un grand nombre d'entrées, il sera sensiblement plus rapide.
Principe
pas sûr de ce que les garanties que vous avez et que vous voulez, donc offre de toute façon.
si vous avez des garanties vous pouvez le faire avec le code très court. L'idée est d'utiliser fonction de substitution de texte de bash pour couper la dernière barre oblique et ce qui suit.
réponse des cas simples aux cas plus complexes de la question initiale.
si le trajet se termine sans coupure (entrée et sortie)
P=/home/smith/Desktop/Test ; echo "${P%/*}"
/home/smith/Desktop
si le chemin se termine par exactement une barre oblique (entrée et sortie)
P=/home/smith/Desktop/Test/ ; echo "${P%/*/}/"
/home/smith/Desktop/
si le chemin d'entrée peut se terminer par zéro ou une barre oblique (pas plus) et que vous voulez que le chemin de sortie se termine sans barre oblique
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 de nombreuses barres obliques étrangères et que vous voulez que le chemin de sortie se termine sans barre oblique
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
utiliser ceci : export MYVAR="$(dirname "$(dirname "$(dirname "$(dirname $PWD)")")")"
si vous voulez 4e répertoire parent
export MYVAR="$(dirname "$(dirname "$(dirname $PWD)")")"
si vous voulez 3ème répertoire parent
export MYVAR="$(dirname "$(dirname $PWD)")"
si vous voulez 2nd parent directory
laid but efficient
function Parentdir()
{
local lookFor_ parent_ switch_ i_
lookFor_=""
#if it is not a file, we need the grand parent
[ -f "$lookFor_" ] || switch_="/.."
#length of search string
i_="${#lookFor_}"
#remove string one by one until it make sens for the system
while [ "$i_" -ge 0 ] && [ ! -d "${lookFor_:0:$i_}" ];
do
let i_--
done
#get real path
parent_="$(realpath "${lookFor_:0:$i_}$switch_")"
#done
echo "
lookFor_:
{lookFor_:0:$i_}: ${lookFor_:0:$i_}
realpath {lookFor_:0:$i_}: $(realpath ${lookFor_:0:$i_})
parent_: $parent_
"
}
lookFor_: /home/Om Namah Shivaya
{lookFor_:0:6}: /home/
realpath {lookFor_:0:6}: /home
parent_: /home
lookFor_: /var/log
{lookFor_:0:8}: /var/log
realpath {lookFor_:0:8}: /UNIONFS/var/log
parent_: /UNIONFS/var
lookFor_: /var/log/
{lookFor_:0:9}: /var/log/
realpath {lookFor_:0:9}: /UNIONFS/var/log
parent_: /UNIONFS/var
lookFor_: /tmp//res.log/..
{lookFor_:0:6}: /tmp//
realpath {lookFor_:0:6}: /tmp
parent_: /
lookFor_: /media/sdc8/../sdc8/Debian_Master//a
{lookFor_:0:35}: /media/sdc8/../sdc8/Debian_Master//
realpath {lookFor_:0:35}: /media/sdc8/Debian_Master
parent_: /media/sdc8
lookFor_: /media/sdc8//Debian_Master/../Debian_Master/a
{lookFor_:0:44}: /media/sdc8//Debian_Master/../Debian_Master/
realpath {lookFor_:0:44}: /media/sdc8/Debian_Master
parent_: /media/sdc8
lookFor_: /media/sdc8/Debian_Master/../Debian_Master/For_Debian
{lookFor_:0:53}: /media/sdc8/Debian_Master/../Debian_Master/For_Debian
realpath {lookFor_:0:53}: /media/sdc8/Debian_Master/For_Debian
parent_: /media/sdc8/Debian_Master
lookFor_: /tmp/../res.log
{lookFor_:0:8}: /tmp/../
realpath {lookFor_:0:8}: /
parent_: /
a commencé à partir de L'idée/commentaire Charles Duffy - Dec 17 '14 à 5: 32 sur le thème Get current directory name (without full path) in a Bash script
#!/bin/bash
#INFO : /q/get-current-directory-name-without-full-path-in-a-bash-script-23114/"$( IFS=/ read -r -a dirs <<<"${dirTree}"; printf '%s\n' "$((${#dirs[@]} - 1))" )"
for(( cnt=0 ; cnt < ${dirNr} ; cnt++))
do
dirName[$cnt]="$( IFS=/ read -r -a dirs <<<"$PWD"; printf '%s\n' "${dirs[${#dirs[@]} - $(( $cnt+1))]}" )"
#information – feedback
echo "$cnt : ${dirName[$cnt]}"
done
}
dirTree=$PWD;
getDirNames;