OS X에서 임의의 파일의 절대 경로를 검색하는 방법


18

Bash 내에서 OS X (Linux의``readlink -f ''와 비슷한) 파일의 절대적이고 표준화 된 경로를 찾기 위해 사용할 수있는 간단한 명령을 찾고 있습니다.

다음 샘플 bash 세션은 원하는 동작을 나타내는``abspath ''라는 [가상] 유틸리티를 설명합니다.

$ pwd
/Users/guyfleegman

$ ls -lR
drwxr-xr-x  4 guyfleegman  crew  136 Oct 30 02:09 foo

./foo:
-rw-r--r--  1 guyfleegman  crew  0 Oct 30 02:07 bar.txt
lrwxr-xr-x  1 guyfleegman  crew  7 Oct 30 02:09 baz.txt -> bar.txt


$ abspath .
/Users/guyfleegman

$ abspath foo
/Users/guyfleegman/foo

$ abspath ./foo/bar.txt
/Users/guyfleegman/foo/bar.txt

$ abspath foo/baz.txt
/Users/guyfleegman/foo/baz.txt

위의 예제에서``abspath ''를 마지막으로 호출 한 것처럼 심볼릭 링크를 자동으로 해결하지는 않지만 여기서는 까다로울 수 없습니다.


답변:


16
function abspath() { pushd . > /dev/null; if [ -d "$1" ]; then cd "$1"; dirs -l +0; else cd "`dirname \"$1\"`"; cur_dir=`dirs -l +0`; if [ "$cur_dir" == "/" ]; then echo "$cur_dir`basename \"$1\"`"; else echo "$cur_dir/`basename \"$1\"`"; fi; fi; popd > /dev/null; }

예 :

abspath / => /

abspath /.DS_Store => /.DS_Store

abspath ~ => /Users/mschrag

cd /tmp; abspath . => /tmp

cd /; abspath .DS_Store => /.DS_Store

11

나는 이것을하는 내장 명령이 있다고 생각하지 않습니다. Jesse Wilson 은이를 위해 bash 스크립트를 작성했습니다.

#!/bin/bash
cd -P -- "$(dirname -- "$1")" &&
printf '%s\n' "$(pwd -P)/$(basename -- "$1")"

그러나 (printing ) 및 and ( 두 경우 모두 인쇄 ) /와 같이 바로 아래의 경로에는 적합하지 않습니다 . 나는 그것을 수정하려고했지만 충분하지 않은 bash-fu는 나를 실패했다./etc//etc.../cwd/.

내 제안은 다음과 같습니다.

#!/usr/bin/env python
import os.path
import sys

for arg in sys.argv[1:]:
    print os.path.abspath(arg)

그대로 저장 /usr/bin/abspath하거나 실행 파일로 만드십시오. 샘플 출력 :

Servus08:~ danielbeck$ abspath .
/Users/danielbeck
Servus08:~ danielbeck$ abspath /tmp
/tmp
Servus08:~ danielbeck$ abspath Documents
/Users/danielbeck/Documents
Servus08:~ danielbeck$ abspath . /tmp Documents
/Users/danielbeck
/tmp
/Users/danielbeck/Documents

당신이 경우 어떻게 심볼릭 링크 해상도를 원하는, 변경 print과 같은 라인 :

    print os.path.realpath(os.path.abspath(arg))

이것을 얻으려면 :

Servus08:~ danielbeck$ abspath . /tmp Documents
/Users/danielbeck
/private/tmp
/Users/danielbeck/Documents

1
첫 번째 쉘 기반 접근 방식으로 올바른 길을 가고 있다고 생각하지만 추가 언어를 도입하고 GNU의`readlink 버전을 컴파일하는 것과 거의 동일하므로 다른 언어를 사용하면 목적을 다소 어길 것이라고 생각합니다. (1) 'OS X에서 (이 작업을 수행 할 수 있다고 가정하지만 아직 확인하지 않았습니다).
Michael Wehner

2
@Michael 당신은 GNU readlink가 설치된 시스템이나 OS X에 있습니까? OS X에는 기본적으로 Python이 있습니다. 이론 상으로는 실제로는 새로운 의존성이 아닙니다. 어쨌든, 내가 당신에게 제공 할 수있는 전부입니다.
Daniel Beck

당신이 암시하는 실용적인 접근 방식은 지나치게 단순하다면 칭찬 할 만하다. 어쨌든 우리가 순수하게 bash로 작성된 것을 대신 하여이 접근법을 취한다면 (절대적으로 가능하고 다른 것에 의존하지 않습니다-단지 한 줄로 쉽게 수행 할 수는 없습니다), 파이썬은 아마도 최선의 선택이 아닙니다. Perl과 Ruby (그리고 아마도 PHP)는 실제 스크립트 파일을 만들 필요없이 명령 줄에서 간결하게이 작업을 수행 할 수 있습니다.
Michael Wehner

1
@Michael : 맞습니다.하지만 제가 언급 한 것은 아닙니다. Jesse Wilson이 작성한 순수 bash로 작성된 90 % 솔루션을 제공합니다. 왜 90 %인지 분석합니다. 그것이 당신에게 아무런 문제가 없다면 괜찮습니다. 또한 파이썬에서 약간 더 복잡한 100 % 솔루션을 제공했습니다. 다른 스크립팅 언어는 더 짧을 수도 있지만 (Perl은 매우 유명합니다. :-) 명령을 저장하려면 추가 파일이 필요합니다. 아니면 사용할 때마다 작성 하시겠습니까? 그렇기 때문에 여러 매개 변수를 처리하는 여러 줄 기능을 추가 한 이유는 1 또는 2 줄이며 다르지 않습니다.
Daniel Beck

2
@ Michael, 왜 OS X에서 파이썬이 좋은 선택이 아니겠습니까? 그것은 실제로 다음과 같은 파이썬 스크립트 인 명령과 함께 제공됩니다.file /usr/bin/xattr
Arjan

8

한 가지 옵션은 coreutils를 설치하고 사용하는 것 greadlink -f입니다. 심볼릭 링크를 해결하고 존재 /Foo/하거나 ~/foo.txt존재하지 않는 경우 작동 하지만 존재하지 않는 /Foo/foo.txt경우 /Foo/작동하지 않습니다.

$ brew install coreutils
$ greadlink -f /etc
/private/etc
$ greadlink -f ~/Documents/
/Users/lauri/Documents
$ greadlink -f ..
/Users
$ greadlink -f //etc/..////
/private
$ greadlink -f /Foo
/Foo
$ greadlink -f /Foo/foo.txt
$ 

이것은 심볼릭 링크를 해결하지 못하며 작동하지 않습니다 /Foo/foo.txt.

abspath() {
  if [ -d "$1" ]; then
    ( cd "$1"; dirs -l +0 )
  else
    ( cd "$(dirname "$1")"; d=$(dirs -l +0); echo "${d%/}/${1##*/}" )
  fi
}

abspath /etc # /etc
abspath ~/Foo/foo.txt # doesn't work
abspath ~/Foo # works
abspath .
abspath ./
abspath ../
abspath ..
abspath /
abspath ~
abspath ~/
abspath ~/Documents
abspath /\"\ \'
abspath /etc/../etc/
abspath /private//etc/
abspath /private//
abspath //private # //private
abspath ./aa.txt
abspath aa.tar.gz
abspath .aa.txt
abspath /.DS_Store
abspath ~/Documents/Books/

dirs -l물결표 확장을 수행합니다. dirs +0스택에 다른 디렉토리가있는 경우 최상위 디렉토리 만 인쇄합니다.


2

파이썬이나 루비로 할 수 있다고 생각합니다.

$ ruby -e 'puts File.expand_path("~/somepath")'

또는 명령으로

#!/usr/bin/env ruby
puts File.expand_path(ARGV[0])

Daniel Beck의 대답에 대한 나의 이전 의견은 여기에도 적용됩니다 (순전히 Bash-y 솔루션을 선호합니다). 다른 언어를 사용하여 이것을 달성한다면, 지금까지 귀하의 솔루션이 가장 간결합니다. :) 또한 루비 호출을 래핑 (예 : function abspath () {ruby -e "puts File.expand_path ( '$ 1')";})하고 내`.profile '에 넣었을 것입니다.
Michael Wehner

1

perl 용 File :: Spec 모듈이 설치되어 있다면 다음과 같이하면됩니다 :

perl -MFile::Spec -e 'print File::Spec->rel2abs("../however/complex/../you/want/to.get"), "\n"'

0

bash / sh 스크립트의 경우 다음과 같은 재귀 함수를 사용할 수 있습니다.

canonical_readlink ()
{
    cd `dirname $1`;
    __filename=`basename $1`;
    if [ -h "$__filename" ]; then
        canonical_readlink `readlink $__filename`;
    else
        echo "`pwd -P`";
    fi
}

answer=$(canonical_readlink $0)

일부 변수 및 명령 대체가 올바르게 인용되지 않았습니다. 와 같은 변수 이름 대신 로컬 변수를 사용할 수 있습니다 __filename. 스크립트는 현재 dirname어쨌든 더 동작 합니다.
Lri

0

다음 OSX 용 라이브러리를 설치하십시오.

brew install coreutils

greadlink -f file.txt

0

coreutils 설치가 옵션이 아닌 경우 다음은 symlinks 조합을 처리합니다. GNU Realpath와 같은 파일 및 폴더에서 작동합니다.

#!/usr/bin/env bash
realpath()
{
    if ! pushd $1 &> /dev/null; then 
        pushd ${1##*/} &> /dev/null
        echo $( pwd -P )/${1%/*}
    else
        pwd -P
    fi
    popd > /dev/null
}

그러나 실제 경로의 상대는 지원하지 않습니다. /programming//a/12498485/869951 이 필요합니다 .


0

제약 조건이 MacOS (당시 OS X) 인 경우 기본적으로 PHP를 사용할 수 있습니다. 파일의 루트 디렉토리를 반환합니다. dirname파일도 가져 오려면 제거하십시오 .

export SOURCE_DIRECTORY="$(php -r 'echo dirname(realpath($argv[1]));' -- "${BASH_SOURCE[0]}")"
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.