Si j'ai un chemin de fichier tel que ...
/home/smith/Desktop/Test
/home/smith/Desktop/Test/
Comment changer la chaîne pour qu'elle devienne le répertoire parent?
par exemple
/home/smith/Desktop
/home/smith/Desktop/
Si j'ai un chemin de fichier tel que ...
/home/smith/Desktop/Test
/home/smith/Desktop/Test/
Comment changer la chaîne pour qu'elle devienne le répertoire parent?
par exemple
/home/smith/Desktop
/home/smith/Desktop/
Réponses:
dir=/home/smith/Desktop/Test
parentdir="$(dirname "$dir")"
Fonctionne également s'il y a une barre oblique.
parentdir=$(dirname `pwd`)
... 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
Utilisez-le echo $(cd ../ && pwd)
tout en travaillant dans le répertoire dont vous souhaitez découvrir le répertoire parent. Cette chaîne présente également l'avantage supplémentaire de ne pas avoir de barres obliques de fin.
echo
ici.
De toute évidence, le répertoire parent est donné en ajoutant simplement le nom de 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 meilleures réponses qui utilisent dirname
, c'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!
EDIT: Si cela ne fonctionne pas, vérifiez que votre cd
n'a pas été modifié, comme c'est parfois le cas,
$ which cd
cd is a function #cd was modified to print extra info, so use "builtin cd" to override
cd ()
{
builtin cd "$@";
ls -FGAhp
}
...
eval
n'est PAS géniale s'il y a une chance d'analyser les entrées des utilisateurs qui pourraient vous mettre dans un endroit inattendu ou exécuter de mauvaises choses contre votre système. Pouvez-vous utiliser à la pushd $dir 2>&1 >/dev/null && pwd && popd 2>&1 >/dev/null
place du eval
?
eval
du tout: faites-le parentdir=$(cd -- "$dir" && pwd)
. Puisque le cd
est exécuté en sous-shell, vous n'avez pas besoin de cd
revenir là où nous étions. Le --
est ici au cas où l'expansion de $dir
commence par un trait d'union. Le but &&
est simplement d'empêcher parentdir
d'avoir un contenu non vide lorsque le cd
n'a pas réussi.
J'aime le code très court, clair et garanti. Point bonus s'il n'exécute pas de programme externe, car le jour où vous aurez besoin de traiter un grand nombre d'entrées, il sera sensiblement plus rapide.
Je ne sais pas quelles garanties vous avez et voulez, donc offrez 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 bash pour couper la dernière barre oblique et tout ce qui suit.
Réponse de cas simples à plus complexes de la question d'origine.
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
${BASH_SOURCE[0]}
laquelle serait le chemin d'accès complet au script s'il n'était pas fourni via source
ou .
.
Si /home/smith/Desktop/Test/../
c'est ce que vous voulez:
dirname 'path/to/child/dir'
comme on le voit ici .
bash: dirname 'Test': syntax error: invalid arithmetic operator (error token is "'Test'")
. Le code lié est également incorrect.
dirname Test
partir du répertoire Test
.
Selon que vous avez besoin de chemins absolus, vous voudrez peut-être faire un pas supplémentaire:
child='/home/smith/Desktop/Test/'
parent=$(dirname "$child")
abs_parent=$(realpath "$parent")
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 le 2è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_: /
Partant de l'idée / du commentaire Charles Duffy - 17 décembre 14 à 17h32 sur le sujet Obtenir le nom du répertoire actuel (sans chemin complet) dans un script Bash
#!/bin/bash
#INFO : /programming/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;
si , pour quelque raison que ce qui vous intéresse pour naviguer dans un certain nombre spécifique de répertoires que vous pouvez également faire: nth_path=$(cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && cd ../../../ && pwd)
. Cela donnerait 3 répertoires aux parents
..
', mais ce n'est peut-être pas tout à fait ce que vous aviez en tête.