bash에서 디렉토리와 상대 경로를 찾기 위해 $ 0 변수를 어떻게 분할합니까?


10

$ 0 변수는 스크립트의 경로 정보를 포함합니다.

  • 경로 정보를 절대 경로로 변경하려면 어떻게해야합니까? ~,., .. 또는 이와 유사한 것을 처리하는 방법을 의미합니까?
  • 경로 정보를 디렉토리와 파일 이름으로 어떻게 분할 할 수 있습니까?

이것을 위해 python / perl을 사용할 수 있지만 가능한 경우 bash를 사용하고 싶습니다.


당신은 무엇을 달성하려고합니까? btw. ~ / foo.sh로 스크립트를 호출하면 내 bash 버전 (GNU bash, 버전 4.1.5 (2) -release- (x86_64-unknown-linux-gnu))으로 $ 0의 홈 디렉토리로 ~가 확장됩니다.
echox

답변:


17

당신은 같은 것들을 처리 할 필요가 없습니다 ~. 쉘이 당신을 위해 그것을합니다. 그렇기 때문에 ~/filename모든 스크립트 또는 프로그램에 전달할 수 있고 작동합니다. 모든 프로그램이 ~자체적으로 처리하지 않고 쉘은 인수를 변환하여 /home/username/filename대신 프로그램에 전달합니다.

$ echo ~/filename
/home/mrozekma/filename

당신은 표준 파일 이름 (같은 것들을 포함하지 않는 한이 필요한 경우 .., 사용) realpath(감사 )

$ realpath ~/../filename
/home/filename

분할 디렉토리 이름과 파일 이름 사용에 경로로 dirnamebasename:

$ dirname /foo/bar/baz
/foo/bar

$ basename /foo/bar/baz
baz

나는 당신이 readlink가 아니라 realpath를 의미한다고 생각합니다. readlink는 일반적인 상황에서 작동하지 않습니다. 즉, 링크가 상대 경로를 사용하고 링크와 동일한 디렉토리에 있지 않은 경우.
Neil Mayhew

@ Neil realpath이 더 좋지만 readlink시도 할 때 효과가있는 것 같습니다. 실패한 예를 알고 있습니까?
Michael Mrozek

1
cd /tmp; touch foo; ln -s foo bar; cd; readlink /tmp/bar. 이것은 당신이 원하는 것을 반환 foo하고 realpath반환합니다 /tmp/foo.
Neil Mayhew

1
@Neil, @Michael : readlink -f(주 -f)는 거의 동일하며 realpath이식성이 더 뛰어납니다 : readlink -fGNU coreutils에는 몇 개의 다른 시스템에도 있습니다; realpath패키지는 별도로 패키지되어 설치되지 않을 수 있습니다 (예 : Ubuntu 10.04 또는 Debian lenny에서 일반적이지 않은 패키지는 5 개뿐).
Gilles 'SO- 악한 중지'11

@ 길 : 좋은 지적. realpath -f에 대해 상기시켜 주셔서 감사합니다.
Neil Mayhew

5

Michael이 언급 한 것처럼 dirname과 basename을 사용하는 것이 원하는 것을 얻는 가장 안전한 방법이어야합니다.

어쨌든 "bash 전용 도구"를 사용하여이 작업을 수행하려면 매개 변수 대체를 사용할 수 있습니다.

echo `basename $PWD`        # Basename of current working directory.
echo "${PWD##*/}"           # Basename of current working directory.
echo
echo `basename $0`          # Name of script.
echo $0                     # Name of script.
echo "${0##*/}"             # Name of script.
echo
filename=test.data
echo "${filename##*.}"      # data
                            # Extension of filename.

이 예제는 Advanced Bash Scripting Guide 에서 직접 가져온 것입니다.

설명은 매우 간단합니다.

$ {var # Pattern} $ var의 프론트 엔드와 일치하는 $ Pattern의 가장 짧은 부분을 $ var에서 제거하십시오. $ {var ## Pattern} $ var의 프론트 엔드와 일치하는 $ Pattern의 가장 긴 부분을 $ var에서 제거하십시오.

정규식 #이나 ##욕심 / 비 욕심 수정 자 와 같은 패턴을보십시오 .

경로 부분의 좀 더 복잡한 추출을 수행해야하는 경우 유용 할 수 있습니다.


5
사용시주의 ${...##...}친구보다는 dirname하고 basename있음을 그들은 모든 경우에 작동하지 않습니다. 예를 들어 두 ${0##*/}${0%/*}같은으로 확장 $0하는 경우 $0포함되어 있지 않습니다 /.
Gilles 'SO- 악마 그만'

@Gilles 나는 왜 ${0%/*}좋은 대안이 아닌지 이해 한다 dirname. 그러나 ? ${0##*/}대신에 사용하면 무엇이 문제 basename입니까?
toxalot

@toxalot 이것에 대한 유일한 문제는 때가 $0뒤에 디렉토리 이름입니다 /. 그러나 나는 dirname더 나은 일을하지 않기 때문에 내 충고를 후회 합니다.
Gilles 'SO- 악의를 멈춰라'

2

realpath 실제 경로를 알려주는 명령입니다 (.. 및 심볼릭 링크 제거 등).

FreeBSD의 표준입니다. 이 토론에 따르면 Linux에서도 사용할 수 있습니다.

http://www.unix.com/shell-programming-scripting/89294-geting-real-path.html

이 토론은 또한 bash 솔루션을 제공합니다.

$ bash -c "cd /foo/../bar/ ; pwd"

1
정확히 다음과 같이 작동합니다 : MYDIR = "$ (cd $ (dirname"$ 0 "); pwd)"
Kevin Cantu
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.