Si j'ai un chemin de fichier tel que ...
/home/smith/Desktop/Test
/home/smith/Desktop/Test/
Comment changer la chaîne pour qu'il s'agisse du répertoire parent?
par exemple.
/home/smith/Desktop
/home/smith/Desktop/
dir=/home/smith/Desktop/Test
parentdir="$(dirname "$dir")"
Fonctionne également s'il y a une barre oblique finale.
... mais ce qui est "vu ici " est cassé. Voici le correctif:
> pwd
/home/me
> x='Om Namah Shivaya'
> mkdir "$x" && cd "$x"
/home/me/Om Namah Shivaya
> parentdir="$(dirname "$(pwd)")"
> echo $parentdir
/home/me
Clairement, le répertoire parent est donné en ajoutant simplement le nom du fichier point-point:
/home/smith/Desktop/Test/.. # unresolved path
Mais vous devez vouloir le chemin résolu (un chemin absolu sans aucun composant de chemin point à point):
/home/smith/Desktop # resolved path
Le problème avec les réponses les plus fréquentes qui utilisent dirname
est qu'elles ne fonctionnent pas lorsque 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 le nourrir /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!
Utilisez simplement echo $(cd ../ && pwd)
lorsque vous travaillez dans le répertoire dont vous voulez connaître le répertoire parent. Cette chaîne présente également l’avantage supplémentaire de ne pas avoir de slash final.
J'aime le code très court, clair et garanti. Si vous n’exécutez pas de programme externe, votre bonus sera d'autant plus rapide que le jour où vous devrez traiter un très grand nombre d'entrées.
Vous ne savez pas exactement quelles sont les garanties que vous avez et ce que vous souhaitez, alors offrez-les 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 fonctionnalité de substitution de texte bash pour couper la dernière barre oblique et ainsi de suite.
Répondez de cas simples à des cas plus complexes de la question initiale.
P=/home/smith/Desktop/Test ; echo "${P%/*}"
/home/smith/Desktop
P=/home/smith/Desktop/Test/ ; echo "${P%/*/}/"
/home/smith/Desktop/
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
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
Selon que vous ayez besoin de chemins absolus ou non, vous pouvez effectuer une étape supplémentaire
child='/home/smith/Desktop/Test/'
parent=$(dirname "$child")
abs_parent=$(realpath "$parent")
Partis de l'idée/commentaire Charles Duffy - 17 déc. 14 à 17:32 sur le sujet Obtenir le nom du répertoire actuel (sans chemin d'accès complet) dans un script Bash
#!/bin/bash
#INFO : https://stackoverflow.com/questions/1371261/get-current-directory-name-without-full-path-in-a-bash-script
# comment : by Charles Duffy - Dec 17 '14 at 5:32
# at the beginning :
declare -a dirName[]
function getDirNames(){
dirNr="$( 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;
utilisez ceci: export MYVAR="$(dirname "$(dirname "$(dirname "$(dirname $PWD)")")")"
si vous voulez le 4ème répertoire parent
export MYVAR="$(dirname "$(dirname "$(dirname $PWD)")")"
si vous voulez le 3ème répertoire parent
export MYVAR="$(dirname "$(dirname $PWD)")"
si vous voulez un deuxième répertoire parent
moche mais efficace
function Parentdir()
{
local lookFor_ parent_ switch_ i_
lookFor_="$1"
#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_: $1
{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_: /