it-swarm.com.de

Das übergeordnete Verzeichnis eines Verzeichnisses in Bash abrufen

Wenn ich einen Dateipfad habe wie ...

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

Wie ändere ich die Zeichenfolge, damit es das übergeordnete Verzeichnis ist?

z.B.

/home/smith/Desktop
/home/smith/Desktop/
148
YTKColumba
dir=/home/smith/Desktop/Test
parentdir="$(dirname "$dir")"

Funktioniert auch, wenn es einen nachgestellten Schrägstrich gibt.

233
Michael Hoffman

... aber was ist "gesehen hier " ist kaputt. Hier ist der Fix:

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

Natürlich wird das übergeordnete Verzeichnis durch einfaches Anhängen des Punkt-Dateinamens angegeben: 

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

Sie müssen jedoch den aufgelösten Pfad (einen absoluten Pfad ohne Punkt-Punkt-Pfadkomponenten) haben:

/home/smith/Desktop             # resolved path

Das Problem mit den ersten Antworten, die dirname verwenden, besteht darin, dass sie nicht funktionieren, wenn Sie einen Pfad mit Punktpunkten eingeben:

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

Das ist mächtiger

dir=/home/smith/Desktop/Test
parentdir=`eval "cd $dir;pwd;cd - > /dev/null"`

Sie können es /home/smith/Desktop/Test/.., aber auch komplexere Pfade wie: 

$ dir=~/Library/../Desktop/../..
$ parentdir=`eval "cd $dir;pwd;cd - > /dev/null"`
$ echo $parentdir
/Users                                  # the fully resolved path!
10
Riaz Rizvi

Wenn /home/smith/Desktop/Test/../ das ist, was Sie wollen:

dirname 'path/to/child/dir'

wie gesehen hier .

7
Jon Egeland

Verwenden Sie einfach echo $(cd ../ && pwd), während Sie in dem Verzeichnis arbeiten, dessen übergeordnetes Verzeichnis Sie herausfinden möchten. Diese Kette hat auch den zusätzlichen Vorteil, dass keine nachlaufenden Schrägstriche vorhanden sind. 

7
Endu A-d

Motivation für eine andere Antwort

Ich mag sehr kurzen, klaren, garantierten Code. Bonuspunkt, wenn kein externes Programm ausgeführt wird, da der Tag, an dem Sie eine große Anzahl von Einträgen verarbeiten müssen, deutlich schneller ist.

Prinzip

Sie sind sich nicht sicher, welche Garantien Sie haben und wollen, und bieten Sie trotzdem an.

Wenn Sie Garantien haben, können Sie dies mit sehr kurzem Code tun. Die Idee ist, die Bash-Textsubstitutionsfunktion zu verwenden, um den letzten Schrägstrich und alles, was folgt, abzuschneiden.

Antwort von einfachen bis komplexeren Fällen der ursprünglichen Frage.

Wenn garantiert ist, dass der Pfad ohne Schrägstrich endet (ein- und ausgehend)

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

Wenn garantiert ist, dass der Pfad mit genau einem Schrägstrich endet (rein und raus)

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

Wenn der Eingabepfad mit null oder einem Schrägstrich (nicht mehr) endet und der Ausgabepfad ohne Schrägstrich enden soll

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

Wenn der Eingabepfad viele überflüssige Schrägstriche enthält und der Ausgabepfad ohne Schrägstrich enden soll

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

Abhängig davon, ob Sie absolute Pfade benötigen, möchten Sie möglicherweise einen zusätzlichen Schritt tun:

child='/home/smith/Desktop/Test/'
parent=$(dirname "$child")
abs_parent=$(realpath "$parent")
1
Marcelo Lacerda

Gestartet von der Idee/Kommentar Charles Duffy - 17. Dezember 14 um 5:32 Uhr zum Thema Aktuellen Verzeichnisnamen (ohne vollständigen Pfad) in einem Bash-Skript abrufen

#!/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;
0
kris

verwenden Sie folgendes: export MYVAR="$(dirname "$(dirname "$(dirname "$(dirname $PWD)")")")", wenn Sie das vierte übergeordnete Verzeichnis möchten 

export MYVAR="$(dirname "$(dirname "$(dirname $PWD)")")" wenn Sie ein drittes übergeordnetes Verzeichnis wünschen 

export MYVAR="$(dirname "$(dirname $PWD)")" wenn Sie das zweite übergeordnete Verzeichnis wünschen

0
Kaustubh

hässlich aber effizient

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_: /
0
magoofromparis