bash에서 파일의 절대 디렉토리를 어떻게 얻습니까?


82

입력 파일을 인수로 사용하여 읽는 bash 스크립트를 작성했습니다.
이 파일에는 사용 된 추가 파일에 대한 일부 경로 (위치 기준)가 포함되어 있습니다.

추가 명령을 실행하기 위해 스크립트를 입력 파일이 포함 된 폴더로 이동하고 싶습니다.

그렇다면 입력 파일에서 폴더 (및 폴더 만)를 가져 오는 방법은 무엇입니까? (리눅스에서.)


입력 파일의 전체 경로를 제공합니까 아니면 현재 작업 디렉토리에 상대적인 경로 만 제공합니까?
dmh

dhm : 입력은 상대 경로를 제공하고 절대 경로 에서 파일 이름을 뺀 값을 원합니다 .
BobMcGee 2013

답변:


152

전체 경로를 얻으려면 다음을 사용하십시오.

readlink -f relative/path/to/file

파일의 디렉토리를 얻으려면 :

dirname relative/path/to/file

두 가지를 결합 할 수도 있습니다.

dirname $(readlink -f relative/path/to/file)

readlink -f시스템에서를 사용할 수없는 경우 다음을 사용할 수 있습니다. * :

function myreadlink() {
  (
  cd "$(dirname $1)"         # or  cd "${1%/*}"
  echo "$PWD/$(basename $1)" # or  echo "$PWD/${1##*/}"
  )
}

상대 경로로 지정된 파일의 디렉토리로만 이동해야하는 경우 절대 경로를 알 필요가 없으며 상대 경로는 완벽하게 합법적이므로 다음을 사용하십시오.

cd $(dirname relative/path/to/file)

당신이 (스크립트가 실행되는 동안) 원래 경로로 다시 이동하려는 경우, 사용 pushd대신에 cd, 그리고 popd당신이 완료되면.


*myreadlink 위의 내용은이 질문의 맥락에서 충분 하지만 위에서 readlink제안한 도구와 관련하여 약간의 제한이 있습니다. 예를 들어 .NET Framework가 다른 파일에 대한 링크를 올바르게 따르지 않습니다 basename.


17
참고 readlink -f불행하게도, OS X에서 작동하지 않습니다.
Emil Sit

전체 경로가 아니라 폴더 만 원합니다. 그러나 이것은 도움이 될만큼 충분히 제공합니다 : readlink -f relativeFileLocation | xargs를있는 dirname
BobMcGee

1
@EmilSit : 당신 말이 맞습니다. 그러나 당신은 brew install coreutils그것을 얻을 수 있습니다. stackoverflow.com/a/4031502/1022967 .
mpettis

3
사용을 권장하지 마십시오 ${1%/*}또는 ${1##*/}대한 대체를 같이 dirname하고 basename. 첫 번째는 간단한 파일 이름 ( dirname foo.barwould, correct, be .)을 제공하면 중단되고 두 번째는 슬래시 ( basename /foo/bar/, would, correct, be bar)로 끝나는 디렉토리에 대해 중단됩니다 .
Camilo Martin

1
어떤 사람들은 빠르다을 위해 그것을 사용하는 경향 할 수있다 @ChenLevy (생각 basename/ dirname내장 기능을하지 않음), 그들은 처음에 작업 갑자기 겉으로 이익을 위해 미래의 어떤 시점에서 파괴를 볼 수 있습니다 이유. 나는 그것을 옵션으로 제안하는 것을 피하거나 그것이 실제로 방탄 susbtitute가 아니라는 것을 부인합니다.
Camilo Martin

19

에 대한 맨 페이지를 살펴보면 realpath다음과 같은 것을 사용합니다.

CONTAININGDIR = $ (실제 경로 $ {FILEPATH % / *})

당신이하려는 것처럼 들리는 것을 할 수 있습니다.


realpath는 상대 DIRS의 심볼릭 링크를 해결 어디 나에게 이상한 않습니다
에릭 Aronesty

감사! 맥 OS에 나를 위해 일한
드미트리 Klochkov

6

이것은 파일과 폴더 모두에서 작동합니다.

absPath(){
    if [[ -d "$1" ]]; then
        cd "$1"
        echo "$(pwd -P)"
    else 
        cd "$(dirname "$1")"
        echo "$(pwd -P)/$(basename "$1")"
    fi
}

4
$cat abs.sh
#!/bin/bash
echo "$(cd "$(dirname "$1")"; pwd -P)"

몇 가지 설명 :

  1. 이 스크립트는 상대 경로를 인수로 가져옵니다. "$1"
  2. 그런 다음 해당 경로의 dirname 부분을 얻습니다 (이 스크립트에 dir 또는 파일을 전달할 수 있음).dirname "$1"
  3. 그런 다음 우리 cd "$(dirname "$1");는이 상대 디렉토리에
  4. pwd -P절대 경로를 얻으십시오. 이 -P옵션은 심볼릭 링크를 피합니다.
  5. 마지막 단계는 우리로 echo그것을

그런 다음 스크립트를 실행하십시오.

abs.sh your_file.txt

1

GitHub에서 새로운 Bash 라이브러리 제품인 realpath-lib 를 사용해보십시오. GitHub는 무료로 제한없이 사용할 수 있도록 커뮤니티에 제공했습니다. 깨끗하고 간단하며 잘 문서화되어 있으므로 배우는 것이 좋습니다. 넌 할 수있어:

get_realpath <absolute|relative|symlink|local file path>

이 기능은 라이브러리의 핵심입니다.

if [[ -f "$1" ]]
then
    # file *must* exist
    if cd "$(echo "${1%/*}")" &>/dev/null
    then
        # file *may* not be local
        # exception is ./file.ext
        # try 'cd .; cd -;' *works!*
        local tmppwd="$PWD"
        cd - &>/dev/null
    else
        # file *must* be local
        local tmppwd="$PWD"
    fi
else
    # file *cannot* exist
    return 1 # failure
fi

# reassemble realpath
echo "$tmppwd"/"${1##*/}"
return 0 # success

}

Bash 4+이며 종속성이 필요하지 않으며 get_dirname, get_filename, get_stemname 및 validate_path도 제공합니다.


0

위 답변의 문제는 "./my-file.txt"와 같이 "./"로 입력 된 파일과 함께 제공됩니다.

해결 방법 (다수) :

    myfile="./somefile.txt"
    FOLDER="$(dirname $(readlink -f "${ARG}"))"
    echo ${FOLDER}

-1

나는 readlink -f를 사용하고 있습니다.

그래서

FULL_PATH=$(readlink -f filename)
DIR=$(dirname $FULL_PATH)

PWD=$(pwd)

cd $DIR

#<do more work>

cd $PWD

5
Bash에서 대문자 변수 이름을 사용하지 마십시오. 언젠가는 이미 존재하는 변수와 충돌 할 것입니다 ... 오, 그리고 오늘은 지금입니다 : 변수 PWD가 Bash에 이미 존재한다는 것을 알고 계 셨습니까? 그 값이 실제로 현재 디렉토리 라는 것을 알고 계십니까? 그리고 더 많은 따옴표를 사용하십시오.
gniourf_gniourf jul
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.