파일 경로에서 파일 디렉토리 경로 가져 오기


400

Bash에서 if VAR="/home/me/mydir/file.c"는 어떻게 얻 "/home/me/mydir"습니까?

답변:


647

dirnamebasename경로 구성 요소를 추출하기 위해 찾고있는 도구는 다음 과 같습니다.

$ VAR=/home/me/mydir/file.c

$ DIR=$(dirname "${VAR}")

$ echo "${DIR}"
/home/me/mydir

$ basename "${VAR}"
file.c

그들은하지 않은 내부 배쉬 명령을하지만 그들은 POSIX 표준의있는 거 부분 (참조 dirname, basename배쉬를 실행할 시스템의 대부분에 사용할 수 있어야하므로)합니다.


4
예를 들어 "$ VAR"이 아닌 변수 이름에 대괄호를 사용하는 이유는 무엇입니까?
user658182

1
stackoverflow.com/questions/8748831/… 위의 질문에 답변합니다.
user658182

1
@ user658182이 특정 예에서는 필요하지 않고 습관이 없어졌습니다.
버려진 카트

95
$ export VAR=/home/me/mydir/file.c
$ export DIR=${VAR%/*}
$ echo "${DIR}"
/home/me/mydir

$ echo "${VAR##*/}"
file.c

와 의존성을 피하기 위해 basenamedirname


3
둘 다 POSIX의 일부이므로 종속성은 문제가되지 않습니다.
orkoden

1
orkoden, 네 말이 맞아. 내 대답의 목표는 두 가지 추가 프로세스를 실행할 의무가 없음을 보여주는 것입니다. bash는 유스 케이스에 충분합니다.
Emmanuel Devaux '11

2
파일 또는 폴더 이름을 전달한 다음 폴더 경로를 계산하기 때문에 Emmanuel의 방법을 사용하고 있습니다. 이 정규식을 사용하면 올바른 일을하는 반면 dirname 함수는 폴더를 입력 할 때 부모 폴더를 반환했습니다.
AnneTheAgile

8
그러나 $ VAR에 경로 정보가 없으면 $ {VAR % / *} / test는 $ VAR / test와 같은 예상치 못한 값을 생성하는 반면 $ (dirname $ VAR)은보다 예측 가능하고 적절한 ./test 값을 생성합니다. 전자는 파일 이름을 디렉토리로 취급하려고 시도하지만 후자는 OK가되기 때문에 큰 문제입니다.
davemyron

19

관련 메모에서 파일 이름이나 상대 경로 만있는 경우 dirname자체적으로 도움이되지 않습니다. 나를 위해, 대답은 끝났다 readlink.

fname='txtfile'    
echo $(dirname "$fname")                # output: .
echo $(readlink -f "$fname")            # output: /home/me/work/txtfile

그런 다음 둘을 결합하여 디렉토리 만 얻을 수 있습니다.

echo $(dirname $(readlink -f "$fname")) # output: /home/me/work

1
둘 이상의 경로 구성 요소가 존재하지 않으면 readlink -m "$fname"주어진 이름을 재귀 적으로 정식화 하는 데 사용해야 합니다.
EDkan

7

대상 파일이 기호 링크가되도록하려면 먼저 파일을 확인하고 원본 파일을 얻을 수 있습니다. 아래 if 절이 도움이 될 수 있습니다.

if [ -h $file ]
then
 base=$(dirname $(readlink $file))
else
 base=$(dirname $file)
fi

5

나는 이것을 가지고 놀고 대안을 생각해 냈습니다.

$ VAR=/home/me/mydir/file.c

$ DIR=`echo $VAR |xargs dirname`

$ echo $DIR
/home/me/mydir

내가 좋아하는 부분은 트리 백업을 쉽게 확장 할 수 있다는 것입니다.

$ DIR=`echo $VAR |xargs dirname |xargs dirname |xargs dirname`

$ echo $DIR
/home

1

다음은 재귀 트리밍에 사용한 스크립트입니다. 물론 $ 1을 원하는 디렉토리로 바꾸십시오.

BASEDIR="$1"
IFS=$'\n'
cd $BASEDIR
 for f in $(find . -type f -name ' *')
 do 
    DIR=$(dirname "$f")
    DIR=${DIR:1}
    cd $BASEDIR$DIR
    rename 's/^ *//' *
 done

0

먼저 /빈 공간 ( )으로 교체 했습니다 . 그런 다음 빈 공간 앞에 모든 문자를 삭제했습니다 ( ). 마지막으로 빈 공간 인 첫 번째 문자 ( ) 를 제거했습니다 .

$ VAR="/home/me/mydir/file.c"

$ echo $VAR | tr '/' ' ' | sed 's/^.* / /' | cut -c2-
file.c

0
HERE=$(cd $(dirname $BASH_SOURCE) && pwd)

여기서 new_path =로 전체 경로를 얻습니다 $(dirname ${BASH_SOURCE[0]}). cd new_path를 사용 하여 현재 디렉토리를 변경 한 후 실행 pwd하여 현재 디렉토리의 전체 경로를 가져옵니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.