[linux] Bash에서 파일 경로를 어떻게 정규화합니까?

나는 변환 할 /foo/bar/../foo

이것을 수행하는 bash 명령이 있습니까?


편집 : 실제 경우에는 디렉토리가 존재합니다.



답변

경로에서 파일 이름의 일부를 잘라내려면 “dirname”과 “basename”이 친구이며 “realpath”도 편리합니다.

dirname /foo/bar/baz
# /foo/bar 
basename /foo/bar/baz
# baz
dirname $( dirname  /foo/bar/baz  )
# /foo 
realpath ../foo
# ../foo: No such file or directory
realpath /tmp/../tmp/../tmp
# /tmp

realpath 대안

realpath쉘에서 지원하지 않는 경우 시도해 볼 수 있습니다

readlink -f /path/here/.. 

또한

readlink -m /path/there/../../ 

와 동일하게 작동

realpath -s /path/here/../../

경로를 정규화하기 위해 존재할 필요가 없다는 점에서


답변

이 작업을 수행하는 직접 bash 명령이 있는지 모르겠지만 일반적으로 수행합니다.

normalDir="`cd "${dirToNormalize}";pwd`"
echo "${normalDir}"

잘 작동합니다.


답변

시도하십시오 realpath. 아래는 공개 소스에 기증 된 전체 소스입니다.

// realpath.c: display the absolute path to a file or directory.
// Adam Liss, August, 2007
// This program is provided "as-is" to the public domain, without express or
// implied warranty, for any non-profit use, provided this notice is maintained.

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <libgen.h>
#include <limits.h>

static char *s_pMyName;
void usage(void);

int main(int argc, char *argv[])
{
    char
        sPath[PATH_MAX];


    s_pMyName = strdup(basename(argv[0]));

    if (argc < 2)
        usage();

    printf("%s\n", realpath(argv[1], sPath));
    return 0;
}

void usage(void)
{
    fprintf(stderr, "usage: %s PATH\n", s_pMyName);
    exit(1);
}


답변

이식성이 뛰어나고 안정적인 솔루션은 파이썬을 사용하는 것입니다. 파이썬은 다윈을 포함하여 거의 모든 곳에 사전 설치되어 있습니다. 두 가지 옵션이 있습니다.

  1. abspath 절대 경로를 반환하지만 심볼릭 링크를 확인하지 않습니다.

    python -c "import os,sys; print(os.path.abspath(sys.argv[1]))" path/to/file

  2. realpath 절대 경로를 반환하면 심볼릭 링크가 해결되어 표준 경로가 생성됩니다.

    python -c "import os,sys; print(os.path.realpath(sys.argv[1]))" path/to/file

각각의 경우 path/to/file상대 또는 절대 경로 일 수 있습니다.


답변

coreutils 패키지의 readlink 유틸리티를 사용하십시오.

MY_PATH=$(readlink -f "$0")


답변

readlink절대 경로를 얻기위한 bash 표준입니다. 또한 경로 또는 경로가 존재하지 않는 경우 빈 플래그를 반환하는 이점이 있습니다 (플래그가 제공됨).

존재하거나 존재하지 않을 수 있지만 부모가있는 디렉토리에 대한 절대 경로를 얻으려면 다음을 사용하십시오.

abspath=$(readlink -f $path)

모든 부모와 함께 존재해야하는 디렉토리의 절대 경로를 얻으려면 다음을 수행하십시오.

abspath=$(readlink -e $path)

주어진 경로를 정식화하고 존재하는 경우 심볼릭 링크를 따르지만 누락 된 디렉토리를 무시하고 경로를 반환하려면 다음과 같습니다.

abspath=$(readlink -m $path)

유일한 단점은 readlink가 링크를 따른다는 것입니다. 링크를 따르지 않으려면 다음 대체 규칙을 사용할 수 있습니다.

abspath=$(cd ${path%/*} && echo $PWD/${path##*/})

$ path의 디렉토리 부분으로 chdir하고 $ path의 파일 부분과 함께 현재 디렉토리를 인쇄합니다. chdir에 실패하면 빈 문자열과 stderr에 오류가 발생합니다.


답변

오래된 질문이지만 쉘 수준에서 전체 경로 이름처리 하는 경우 훨씬 간단한 방법 이 있습니다 .

   abspath = "$ (cd"$ path "&& pwd)"

CD는 서브 쉘에서 발생하므로 기본 스크립트에 영향을 미치지 않습니다.

쉘 내장 명령이 -L 및 -P를 허용한다고 가정하면 다음과 같은 두 가지 변형이 있습니다.

   abspath = "$ (cd -P"$ path "&& pwd -P)" "# 심볼릭 링크가 해결 된 물리적 경로
   abspath = "$ (cd -L"$ path "&& pwd -L)" "# 논리적 경로 보존 심볼릭 링크

개인적으로, 어떤 이유로 든 상징적 인 링크에 매료되지 않으면 나중에이 접근법이 거의 필요하지 않습니다.

참고 : 스크립트가 현재 디렉토리를 나중에 변경하더라도 작동하는 스크립트의 시작 디렉토리를 얻는 변형.

name0 = "$ (기본 이름"$ 0 ")"; # 기본 스크립트 이름
dir0 = "$ (cd"$ (dirname "$ 0") ""&& pwd) "; # 절대 시작 디렉토리

CD를 사용하면 스크립트가 ./script.sh와 같은 명령으로 실행 되더라도 cd / pwd없이 종종 ..를 제공하는 경우에도 항상 절대 디렉토리를 갖게됩니다. 스크립트가 나중에 CD를 수행하는 경우에는 쓸모가 없습니다.