Bash에서 디렉토리의 부모 얻기


207

다음과 같은 파일 경로가 있다면 ...

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

부모 디렉토리가되도록 문자열을 어떻게 변경합니까?

예 :

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

4
단순히 ' ..' 를 사용할 수는 있지만 아마도 마음에 들지 않은 것일 수도 있습니다.
Jonathan Leffler

답변:


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

후행 슬래시가있는 경우에도 작동합니다.


14
내부 인용문이 중요하거나 모든 데이터를
잃어 버릴 것입니다

10
그리고 현재 작업 디렉토리의 부모를 얻기 위해 사용하는 변형 : parentdir=$(dirname `pwd`)
TheGrimmScientist

3
이 방법은 "못생긴"이름에는 안전하지 않습니다. "-rm -rf"와 같은 이름은 원하는 동작을 중단합니다. 아마 "." 의지도. 그 가장 좋은 방법인지 잘 모르겠지만, 내가 별도의 만든 여기에 질문을 "정확성에 초점을 맞춘" stackoverflow.com/questions/40700119/...
VasiliNovikov

4
@Christopher Shroba 그래, 따옴표를 생략하고 HDD가 부분적으로 지워졌습니다. 나는 정확히 무슨 일이 일어 났는지 기억하지 못한다 : 아마도 인용되지 않은 공백 디렉토리는 대상 디렉토리 대신 부모 디렉토리를 지우 게 할 것이다. 내 스크립트는 / home / xxx / 폴더를 지웠다.
catamphetamine

3
오, 좋아, 명령에 대해 이미 삭제 명령을 발행하지 않는 한 데이터가 손실되는 것은 없습니다. 공백 문자에서 분리되어 예상보다 훨씬 많은 것을 제거하려고 시도한 경로의 문제 일뿐입니까?
Christopher Shroba

18

...하지만 " 여기에 보이는 "것이 깨졌습니다. 수정 사항은 다음과 같습니다.

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

14

echo $(cd ../ && pwd)부모 디렉토리를 찾으려는 디렉토리에서 작업 하는 동안 사용하십시오 . 이 체인은 또한 슬래시가없는 장점이 있습니다.


당신은 echo여기에 필요하지 않습니다 .
gniourf_gniourf

14

분명히 도트 디렉토리 파일 이름을 추가하여 상위 디렉토리가 제공됩니다.

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

그러나 해결 된 경로 (점-점 경로 구성 요소가없는 절대 경로)가 필요합니다.

/home/smith/Desktop             # resolved path

를 사용하는 최상위 답변의 문제 dirname는 점이있는 경로를 입력하면 작동하지 않는다는 것입니다.

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

이것은 더 강력합니다 :

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

당신은 /home/smith/Desktop/Test/..뿐만 아니라 다음과 같은 더 복잡한 경로를 공급할 수 있습니다

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

편집 : 작동하지 않으면 cd때로는 일반적인 관행과 같이 수정되지 않았는지 확인하십시오 .

$ 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사용자 입력을 구문 분석하여 시스템에 대해 나쁜 일을 예상하지 않거나 어딘가에 놓을 수있는 사용자 입력을 구문 분석 할 수있는 경우 사용 은 좋지 않습니다. pushd $dir 2>&1 >/dev/null && pwd && popd 2>&1 >/dev/null대신에 사용할 수 있습니까 eval?
dragon788

2
당신은 전혀 필요하지 않습니다 eval: 그냥하십시오 parentdir=$(cd -- "$dir" && pwd). cd이 하위 쉘에서 실행 되므로 cd이전 위치 로 돌아갈 필요가 없습니다 . 는 --경우 여기의 확장이다 $dir하이픈으로 시작됩니다. 은 &&단지 방지하는 것입니다 parentdir이 때 비어 있지 않은 내용을 가지고 cdsuceed하지 않았다.
gniourf_gniourf

8

다른 답변을위한 동기 부여

나는 매우 짧고 명확하며 보장 된 코드를 좋아합니다. 외부 프로그램을 실행하지 않는 경우 보너스 포인트는 많은 수의 항목을 처리 해야하는 날이므로 눈에 띄게 빠릅니다.

원리

무엇을 보장하고 원하는지 확실하지 않으므로 어쨌든 제공하십시오.

보증이 있으면 매우 짧은 코드로 할 수 있습니다. 아이디어는 bash 텍스트 대체 기능을 사용하여 마지막 슬래시와 그 다음에 오는 것을 잘라내는 것입니다.

원래 질문의 간단한 사례에서 더 복잡한 사례에 대한 답변.

슬래시없이 경로가 종료되도록 보장 된 경우 (입출고)

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

경로가 정확히 하나의 슬래시로 끝나는 것이 보장되는 경우 (입력 및 출력)

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

입력 경로가 0 또는 하나의 슬래시로 끝나고 슬래시없이 출력 경로를 끝내려는 경우

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

1
환상적인 답변. 그는 스크립트 내 에서이 작업을 수행 할 수있는 방법을 찾고있는 것처럼 보이므로 (스크립트의 현재 디렉토리와 부모를 찾고 스크립트가있는 위치와 관련이있는 작업을 수행하십시오) 이것은 훌륭한 답변이며 더 많은 것을 제어 할 수 있습니다 입력이에 대한 매개 변수 확장을 사용하여 후행 슬래시 여부가 ${BASH_SOURCE[0]}이를 통해 공급되지 않은 경우 스크립트의 전체 경로가 될 것이다 source또는 ..
dragon788

7

/home/smith/Desktop/Test/../원하는 것이 있다면 :

dirname 'path/to/child/dir'

여기 에서 본 .


1
죄송합니다, bash 스크립트처럼, 파일 경로가있는 변수가 있습니다
YTKColumba

해당 코드를 실행하면 오류가 발생 bash: dirname 'Test': syntax error: invalid arithmetic operator (error token is "'Test'")합니다. 연결된 코드도 잘못되었습니다.
Michael Hoffman

dirname Test디렉토리에서 실행 해보십시오 Test.
Jon Egeland

1

절대 경로가 필요한지 여부에 따라 추가 단계를 수행 할 수 있습니다.

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

0

이것을 사용하십시오 : export MYVAR="$(dirname "$(dirname "$(dirname "$(dirname $PWD)")")")"네 번째 부모 디렉토리를 원한다면

export MYVAR="$(dirname "$(dirname "$(dirname $PWD)")")" 세 번째 부모 디렉토리를 원한다면

export MYVAR="$(dirname "$(dirname $PWD)")" 두 번째 부모 디렉토리를 원한다면


고마워!, 내가 찾던 것.
Josue Abarca

0

추악하지만 효율적인

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

아이디어 / 댓글에서 시작 Charles Duffy-12 월 17 '14 일 오전 5:32 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;

0

어떤 이유로 든 특정 수의 디렉토리를 탐색하려는 경우 다음을 수행 할 수도 있습니다 nth_path=$(cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && cd ../../../ && pwd).. 이것은 3 부모님 디렉토리를 줄 것이다


더 간단한 $ BASH_SOURCE 대신 $ {BASH_SOURCE [0]} 인 이유
Nam G VU
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.