Uzyskiwanie rodzica katalogu w Bash

Jeśli mam ścieżkę do pliku taką jak...

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

Jak zmienić łańcuch znaków, aby był katalogiem nadrzędnym?

Np.

/home/smith/Desktop
/home/smith/Desktop/
Author: Nathan, 2011-12-08

10 answers

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

Działa, jeśli jest też końcowy ukośnik.

 197
Author: Michael Hoffman,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-01-10 16:39:30

...ale to, co" widziane tutaj " jest zepsute. Oto poprawka:

> pwd
/home/me
> x='Om Namah Shivaya'
> mkdir "$x" && cd "$x"
/home/me/Om Namah Shivaya
> parentdir="$(dirname "$(pwd)")"
> echo $parentdir
/home/me
 12
Author: Andreas Spindler,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-07-04 09:21:39

Oczywiście Katalog nadrzędny jest podany przez dodanie nazwy pliku dot-dot:

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

Ale musisz chcieć, aby została rozwiązana ścieżka (ścieżka absolutna bez żadnych składników dot-dot path):

/home/smith/Desktop             # resolved path

Problem z najlepszymi odpowiedziami, które używają dirname, polega na tym, że nie działają, gdy wchodzi się do ścieżki z kropkami:

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

To jest mocniejsze :

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

Można go karmić /home/smith/Desktop/Test/.., ale także bardziej złożone ścieżki, takie jak:

$ dir=~/Library/../Desktop/../..
$ parentdir=`eval "cd $dir;pwd;cd - > /dev/null"`
$ echo $parentdir
/Users                                  # the fully resolved path!
 9
Author: Riaz Rizvi,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-11-23 16:51:54

If /home/smith/Desktop/Test/../ is what you want:

dirname 'path/to/child/dir'

Jak widać tutaj .

 7
Author: Jon,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-12-08 04:26:52

Po prostu użyj echo $(cd ../ && pwd) podczas pracy w katalogu, którego Katalog nadrzędny chcesz dowiedzieć się. Ten łańcuch ma również dodatkową zaletę, że nie ma końcowych cięć.

 5
Author: Endu A-d,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-12-28 11:22:45

W zależności od tego, czy potrzebujesz ścieżek bezwzględnych, możesz wykonać dodatkowy krok:

child='/home/smith/Desktop/Test/'
parent=$(dirname "$child")
abs_parent=$(realpath "$parent")
 1
Author: Marcelo Lacerda,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-12-28 11:26:08

Motywacja do innej odpowiedzi

Lubię bardzo krótki, jasny, gwarantowany kod. Punkt bonusowy, jeśli nie uruchomi zewnętrznego programu, od dnia, w którym musisz przetworzyć ogromną liczbę wpisów, będzie zauważalnie szybszy.

Zasada

Nie wiem, jakie gwarancje masz i chcesz, więc i tak oferuj.

Jeśli masz gwarancje, możesz to zrobić za pomocą bardzo krótkiego kodu. Chodzi o to, aby użyć funkcji zastępowania tekstu Basha, aby wyciąć ostatni Ukośnik i cokolwiek / align = "left" /

Odpowiedź od prostych do bardziej złożonych przypadków pierwotnego pytania.

Jeśli ścieżka ma gwarancję zakończenia bez ukośnika (in I out)

P=/home/smith/Desktop/Test ; echo "${P%/*}"
/home/smith/Desktop
Jeśli ścieżka kończy się dokładnie jednym ukośnikiem (in and out)
P=/home/smith/Desktop/Test/ ; echo "${P%/*/}/"
/home/smith/Desktop/

Jeśli ścieżka wejściowa może kończyć się zerem lub jednym ukośnikiem (nie więcej) i chcesz, aby ścieżka wyjściowa kończyła się bez ukośnika

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

Jeśli ścieżka wejściowa może mieć wiele obcych ukośników i chcesz, aby ścieżka wyjściowa kończyła się bez ukośnika

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
Author: Stéphane Gourichon,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-07-15 10:26:21

Użyj tego : export MYVAR="$(dirname "$(dirname "$(dirname "$(dirname $PWD)")")")" jeśli chcesz mieć 4-ty Katalog nadrzędny

export MYVAR="$(dirname "$(dirname "$(dirname $PWD)")")" jeśli chcesz mieć trzeci Katalog nadrzędny

export MYVAR="$(dirname "$(dirname $PWD)")" jeśli chcesz mieć drugi Katalog nadrzędny

 0
Author: Kaustubh,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-11-16 12:57:12

Brzydki, ale skuteczny

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
Author: magoofromparis,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-02-20 13:36:25

Zaczęło się od pomysłu / komentarz Charles Duffy-17 grudnia ' 14 o 5: 32 w temacie Get current directory name (without full path) in a bash script

#!/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
Author: kris,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-09-24 19:25:02