Nice programing

상대 경로를 절대 경로로 변환 하시겠습니까?

nicepro 2021. 1. 5. 21:12
반응형

상대 경로를 절대 경로로 변환 하시겠습니까?


이 경로가 중복되는지 확실하지 않습니다. 상대 경로가 주어지면 쉘 스크립트를 사용하여 절대 경로를 어떻게 결정합니까?

예:

relative path: /x/y/../../a/b/z/../c/d

absolute path: /a/b/c/d

에서 이 소스가 온다 :

#!/bin/bash

# Assume parameter passed in is a relative path to a directory.
# For brevity, we won't do argument type or length checking.

ABS_PATH=`cd "$1"; pwd` # double quotes for paths that contain spaces etc...
echo "Absolute path: $ABS_PATH"

예를 들어 Cwd::abs_path


내가 유닉스에서 만난 가장 신뢰할 수있는 방법은 readlink -f다음과 같습니다.

$ readlink -f /x/y/../../a/b/z/../c/d
/a/b/c/d

몇 가지주의 사항 :

  1. 이것은 또한 모든 심볼릭 링크를 해결하는 부작용이 있습니다. 이것은 바람직하거나 바람직하지 않을 수 있지만 일반적으로 그렇습니다.
  2. readlink존재하지 않는 디렉토리를 참조하면 빈 결과가 표시됩니다. 존재하지 않는 경로를 지원하려면 readlink -m대신 사용하십시오. 불행히도이 옵션은 2005 년 이전에 출시 된 readlink 버전에는 존재하지 않습니다.

사용

# Directory
relative_dir="folder/subfolder/"
absolute_dir="$( cd "$relative_dir" && pwd )"

# File
relative_file="folder/subfolder/file"
absolute_file="$( cd "${relative_file%/*}" && pwd )"/"${relative_file##*/}"
  • ${relative_file%/*} 다음과 같은 결과입니다. dirname "$relative_file"
  • ${relative_file##*/} 다음과 같은 결과입니다. basename "$relative_file"

주의 사항 : 심볼릭 링크를 해결하지 않습니다 (예 : 경로를 정규화하지 않음) => 심볼릭 링크를 사용하는 경우 모든 중복을 구별하지 못할 수 있습니다.


사용 realpath

명령 realpath이 일을합니다. 대안은 readlink -e(또는 readlink -f) 을 사용하는 것입니다 . 그러나 realpath기본적으로 자주 설치되지는 않습니다. 확실하지 realpath않거나 readlink존재하는 경우 perl을 사용하여 대체 할 수 있습니다 (아래 참조).


사용

Steven Kramerrealpath 는 시스템에서 사용할 수없는 경우 쉘 별칭을 제안 합니다.

$ alias realpath="perl -MCwd -e 'print Cwd::realpath(\$ARGV[0]),qq<\n>'"
$ realpath path/folder/file
/home/user/absolute/path/folder/file

또는 직접 펄 사용을 선호하는 경우 :

$ perl -MCwd -e 'print Cwd::realpath($ARGV[0]),qq<\n>' path/folder/file
/home/user/absolute/path/folder/file

이 한 줄짜리 perl 명령은 Cwd::realpath. 실제로 세 가지 펄 함수가 있습니다. 단일 인수를 취하고 절대 경로 이름을 반환합니다. 아래 세부 사항은 Perl5> Core modules> Cwd 문서에서 가져온 것 입니다.

  • abs_path()와 동일한 알고리즘을 사용합니다 getcwd(). 심볼릭 링크 및 상대 경로 구성 요소 ( ...)는에서 같이 표준 경로 이름을 반환하도록 확인됩니다 realpath.

    use Cwd 'abs_path';
    my $abs_path = abs_path($file);
    
  • realpath() 의 동의어입니다. abs_path()

    use Cwd 'realpath';
    my $abs_path = realpath($file);
    
  • fast_abs_path() 더 위험하지만 잠재적으로 더 빠른 버전 abs_path()

    use Cwd 'fast_abs_path';
    my $abs_path = fast_abs_path($file);
    

이 함수는 요청시에만 내보내 지므로 => arielf가 지적한 "Undefined subroutine" 오류 Cwd를 방지하기 위해 사용 하십시오 . 이 세 가지 함수를 모두 가져 오려면 한 줄을 사용할 수 있습니다 .use Cwd

use Cwd qw(abs_path realpath fast_abs_path);

'realpath'를 살펴보십시오.

$ realpath

usage: realpath [-q] path [...]

$ realpath ../../../../../

/data/home

수년에 걸쳐이 문제를 여러 번 겪었고 이번에는 OSX와 Linux에서 사용할 수있는 순수한 bash 휴대용 버전이 필요했기 때문에 계속해서 다음을 작성했습니다.

살아있는 버전은 여기에 있습니다.

https://github.com/keen99/shell-functions/tree/master/resolve_path

하지만 그래서, 여기에 현재 버전이 있습니다 (잘 테스트되었다고 느낍니다 ..하지만 피드백에 열려 있습니다!)

평범한 bourne shell (sh)에서 작동하도록 만드는 것이 어렵지 않을 수도 있지만 시도하지 않았습니다. $ FUNCNAME을 너무 좋아합니다. :)

#!/bin/bash

resolve_path() {
    #I'm bash only, please!
    # usage:  resolve_path <a file or directory> 
    # follows symlinks and relative paths, returns a full real path
    #
    local owd="$PWD"
    #echo "$FUNCNAME for $1" >&2
    local opath="$1"
    local npath=""
    local obase=$(basename "$opath")
    local odir=$(dirname "$opath")
    if [[ -L "$opath" ]]
    then
    #it's a link.
    #file or directory, we want to cd into it's dir
        cd $odir
    #then extract where the link points.
        npath=$(readlink "$obase")
        #have to -L BEFORE we -f, because -f includes -L :(
        if [[ -L $npath ]]
         then
        #the link points to another symlink, so go follow that.
            resolve_path "$npath"
            #and finish out early, we're done.
            return $?
            #done
        elif [[ -f $npath ]]
        #the link points to a file.
         then
            #get the dir for the new file
            nbase=$(basename $npath)
            npath=$(dirname $npath)
            cd "$npath"
            ndir=$(pwd -P)
            retval=0
            #done
        elif [[ -d $npath ]]
         then
        #the link points to a directory.
            cd "$npath"
            ndir=$(pwd -P)
            retval=0
            #done
        else
            echo "$FUNCNAME: ERROR: unknown condition inside link!!" >&2
            echo "opath [[ $opath ]]" >&2
            echo "npath [[ $npath ]]" >&2
            return 1
        fi
    else
        if ! [[ -e "$opath" ]]
         then
            echo "$FUNCNAME: $opath: No such file or directory" >&2
            return 1
            #and break early
        elif [[ -d "$opath" ]]
         then 
            cd "$opath"
            ndir=$(pwd -P)
            retval=0
            #done
        elif [[ -f "$opath" ]]
         then
            cd $odir
            ndir=$(pwd -P)
            nbase=$(basename "$opath")
            retval=0
            #done
        else
            echo "$FUNCNAME: ERROR: unknown condition outside link!!" >&2
            echo "opath [[ $opath ]]" >&2
            return 1
        fi
    fi
    #now assemble our output
    echo -n "$ndir"
    if [[ "x${nbase:=}" != "x" ]]
     then
        echo "/$nbase"
    else 
        echo
    fi
    #now return to where we were
    cd "$owd"
    return $retval
}

다음은 brew 덕분에 고전적인 예입니다.

%% ls -l `which mvn`
lrwxr-xr-x  1 draistrick  502  29 Dec 17 10:50 /usr/local/bin/mvn@ -> ../Cellar/maven/3.2.3/bin/mvn

이 함수를 사용하면 -real- 경로를 반환합니다.

%% cat test.sh
#!/bin/bash
. resolve_path.inc
echo
echo "relative symlinked path:"
which mvn
echo
echo "and the real path:"
resolve_path `which mvn`


%% test.sh

relative symlinked path:
/usr/local/bin/mvn

and the real path:
/usr/local/Cellar/maven/3.2.3/libexec/bin/mvn

도움이 될 수 있습니다.

$path = "~user/dir/../file" 
$resolvedPath = glob($path); #   (To resolve paths with '~')
# Since glob does not resolve relative path, we use abs_path 
$absPath      = abs_path($path);

참조 URL : https://stackoverflow.com/questions/4045253/converting-relative-path-into-absolute-path

반응형