현재 작업 디렉토리를 스크립트의 디렉토리로 설정하는 방법은 무엇입니까?


569

bash 스크립트를 작성 중입니다. 현재 작업 디렉토리가 항상 스크립트가있는 디렉토리가되어야합니다.

기본 동작은 스크립트의 현재 작업 디렉토리가 내가 실행하는 쉘의 디렉토리이지만이 동작을 원하지 않습니다.


/ usr / bin과 같은 랩퍼 스크립트를 (하드 코딩 된) 올바른 디렉토리에 넣고 스크립트를 실행하는 것을 고려해 보셨습니까?
Dagg Nabbit

2
왜 스크립트 디렉토리가 필요합니까? 근본적인 문제를 해결하는 더 좋은 방법이있을 것입니다.
bstpierre

12
나는 당신이 "분명히 바람직하지 않은"이라고 부르는 행동이 실제로 완전히 필요하다는 것을 지적하고 싶습니다. 내가 실행 myscript path/to/file하면 스크립트가 발생하는 디렉토리가 아니라 내 현재 디렉토리에 상대적인 경로 / 파일 / 파일을 평가할 것으로 기대합니다 또한 ssh remotehost bash < ./myscriptBASH FAQ에서 언급했듯이 스크립트 실행에서 어떤 일이 발생 했습니까?
Gordon Davisson


3
cd "${BASH_SOURCE%/*}" || exit
caw

답변:


655
#!/bin/bash
cd "$(dirname "$0")"

7
dirname은 '.'을 반환합니다. Windows에서 bash를 사용할 때. 그래서 바울의 대답이 더 좋습니다.
Tvaroh

7
'.'도 반환 맥 OSX에서
벤 클레이튼

4
심볼릭 링크가의 일부를 구성하면 문제가 발생할 수 있습니다 $0. 예를 들어 ../../스크립트에서 스크립트 위치보다 2 단계 높은 디렉토리를 참조 할 것으로 예상 할 수 있지만 심볼릭 링크가 작동중인 경우 반드시 그런 것은 아닙니다.
Brian Gordon

20
당신과 같이 스크립트를 호출하는 경우 ./script, .올바른 디렉토리이며,로 변경 .그것은 또한 매우 디렉토리에 끝날 script현재 작업 디렉토리에 위치, 즉.
ndim

6
현재 디렉토리에서 스크립트를 실행 bash script.sh하면 값은 $0입니다 script.sh. cd명령이 "작동" 하는 유일한 방법 은 실패한 명령에 신경 쓰지 않기 때문입니다. set -o errexit(일명 :) 을 사용 set -e하여 스크립트가 실패한 명령을 지나치지 않도록 cd script.sh하려면 오류로 인해 작동하지 않습니다 . 확실한 [bash 특정] 방법은 다음과 같습니다cd "$(dirname ${BASH_SOURCE[0]})"
Bruno Bronosky

322

다음도 작동합니다.

cd "${0%/*}"

구문은 StackOverflow 답변 에 자세히 설명되어 있습니다.



25
경로에 공백이 있으면 따옴표로 묶는 것을 잊지 마십시오. 즉 cd "$ {0 % / *}"
H.Rabiee

17
스크립트가 호출 된 경우 실패 bash script.sh$0파일의 이름 일뿐입니다
Chris Watts

17
나는이 대답이 너무 간결하다고 말할 것입니다. 구문에 대해서는 거의 배우지 않습니다. 이것을 읽는 방법에 대한 설명이 도움이 될 것입니다.
fraxture

2
이 속임수도 서브 쉘을 생성하지 않으므로 속력 괴물에게 좋습니다.
teknopaul

184

다음의 간단한 단일 라이너를 사용해보십시오.


모든 UNIX / OSX / Linux

dir=$(cd -P -- "$(dirname -- "$0")" && pwd -P)

세게 때리다

dir=$(cd -P -- "$(dirname -- "${BASH_SOURCE[0]}")" && pwd -P)

참고 : 명령 옵션의 끝을 나타 내기 위해 명령에 이중 대시 (-)가 사용되므로 대시 또는 기타 특수 문자가 포함 된 파일은 명령을 중단하지 않습니다.

참고 : Bash에서는를 ${BASH_SOURCE[0]}선호하여 사용하십시오. $0그렇지 않으면 경로를 소싱 할 때 경로가 중단 될 수 있습니다 ( source/ .).


Linux, Mac 및 기타 * BSD의 경우 :

cd "$(dirname "$(realpath "$0")")";

참고 : realpathUbuntu와 같이 가장 널리 사용되는 Linux 배포판에 기본적으로 설치해야하지만 일부 경우에는 누락 될 수 있으므로 설치해야합니다.

참고 : Bash를 사용 ${BASH_SOURCE[0]}하는 경우을 선호하십시오 $0. 그렇지 않으면 경로를 소싱 할 때 경로가 끊어 질 수 있습니다 ( source/ .).

그렇지 않으면 다음과 같은 것을 시도 할 수 있습니다 (첫 번째 기존 도구를 사용합니다).

cd "$(dirname "$(readlink -f "$0" || realpath "$0")")"

Linux 전용 :

cd "$(dirname "$(readlink -f "$0")")"

* BSD / Mac에서 GNU readlink 사용하기 :

cd "$(dirname "$(greadlink -f "$0")")"

참고 : coreutils설치 해야합니다 (예 : 1. Homebrew 설치 , 2. brew install coreutils).


bash에서

bash에서는 다음 과 같이 매개 변수 확장 을 사용하여이를 수행 할 수 있습니다 .

cd "${0%/*}"

그러나 스크립트가 동일한 디렉토리에서 실행되면 작동하지 않습니다.

또는 bash에서 다음 기능을 정의 할 수 있습니다.

realpath () {
  [[ $1 = /* ]] && echo "$1" || echo "$PWD/${1#./}"
}

이 함수는 1 개의 인수를 갖습니다. 인수에 이미 절대 경로가 있으면 그대로 인쇄하고, 그렇지 않으면 $PWD변수 + 파일 이름 인수 ( ./접두사 없이 )를 인쇄 하십시오 .

또는 다음은 데비안 .bashrc파일 에서 가져온 버전입니다 .

function realpath()
{
    f=$@
    if [ -d "$f" ]; then
        base=""
        dir="$f"
    else
        base="/$(basename "$f")"
        dir=$(dirname "$f")
    fi
    dir=$(cd "$dir" && /bin/pwd)
    echo "$dir$base"
}

관련 :

또한보십시오:

Mac에서 GNU의 readlink -f 동작을 얻으려면 어떻게해야합니까?


4
그것은 syslink를 해결하고 다른 OS를 설명하기 때문에 인기있는 것보다 훨씬 더 나은 대답입니다. 감사!
Dennis

이 답변에 감사드립니다. 맨 위는 내 Mac에서 작동했지만 ...- 스위치는 cp@kenorb 명령에서 무엇을합니까?
TobyG

3
--명령에서 이중 대시 ( )가 사용되어 명령 옵션의 끝을 나타내므로 대시 나 기타 특수 문자가 포함 된 파일은 명령을 중단하지 않습니다. 예를 들어 시도를 통해 파일을 생성 touch "-test"하고 touch -- -test다음을 통해 파일을 제거 rm "-test"하고 rm -- -test, 그 차이를 참조하십시오.
kenorb

1
가능한 경우 upvote를 제거합니다. realpath는 사용되지 않습니다 unix.stackexchange.com/questions/136494/…
lsh

1
@lsh realpathGNU가 아니라 데비안 패키지 만 더 이상 사용되지 않습니다 realpath. 확실하지 않다고 생각되면 편집을 제안 할 수 있습니다.
kenorb

73
cd "$(dirname "${BASH_SOURCE[0]}")"

그것은 간단합니다. 효과가있다.


1
이것이 정답입니다. OSX 및 Linux Ubuntu에서 작동합니다.
David Rissato Cruz

5
스크립트 B가 다른 스크립트 A에서 제공되고 스크립트 B에 상대적인 경로를 사용해야 할 때 유용합니다. 감사합니다.
Enrico

5
이것은 또한 Cygwin 에서 Windows를 만질만큼 불행한 사람들을 위해 작동합니다 .
Bruno Bronosky

3
또는cd "${BASH_SOURCE%/*}" || exit
caw

macOS Mojave에서 작업
Juan Boero

6

허용 된 답변은 into와 같이 다른 곳에서 심볼릭 링크되지 않은 스크립트에 적합합니다 $PATH.

#!/bin/bash
cd "$(dirname "$0")"

그러나 스크립트가 심볼릭 링크를 통해 실행되면

ln -sv ~/project/script.sh ~/bin/; 
~/bin/script.sh

이것은 ~/bin/디렉토리가 아닌 디렉토리 로 들어갑니다. ~/project/목적이 cd상대 디렉토리 를 포함 하는 것이 목적이라면 스크립트가 깨질 것입니다~/project/

symlink 안전 답변은 다음과 같습니다.

#!/bin/bash
cd "$(dirname "$(readlink -f "${BASH_SOURCE[0]}")")"

readlink -f 잠재적으로 링크 된 파일의 절대 경로를 해결하려면 필수입니다.

따옴표는 잠재적으로 공백을 포함 할 수있는 파일 경로를 지원하는 데 필요합니다 (나쁜 방법이지만 이것이 사실이 아니라고 가정하는 것은 안전하지 않습니다).


4

이 스크립트는 저에게 효과적입니다.

#!/bin/bash
mypath=`realpath $0`
cd `dirname $mypath`
pwd

pwd 명령 줄은 스크립트의 위치를 ​​스크립트를 어디에서 실행하든 현재 작업 디렉토리로 표시합니다.


3
realpath어디에나 설치되지 않을 것입니다. OP의 상황에 따라 중요하지 않을 수 있습니다.
bstpierre

내 시스템에는 realpath없지만 readlink비슷한 것 같습니다.
추후 공지가있을 때까지 일시 중지되었습니다.

2
어떤 경로에 기본적으로 리얼 패스가 설치되어 있지 않습니까? 우분투가 있습니다.
kenorb


1
cd "`dirname $(readlink -f ${0})`"

대답을 설명해 주시겠습니까?
Zulu

1
이 코드는 문제를 해결하는 데 도움이 될 수 있지만 질문에 그리고 / 또는 어떻게 대답 하는지 는 설명하지 않습니다 . 이러한 추가 맥락을 제공하면 장기적인 교육 가치가 크게 향상 될 것입니다. 제발 편집 제한 및 가정이 적용되는 것을 포함하여, 설명을 추가 답변을.
Toby Speight

-5
echo $PWD

PWD는 환경 변수입니다.


5
스크립트가있는 디렉토리가 아니라 from 디렉토리 만 제공합니다.
dagelf

-6

현재 작업 디렉토리를 인쇄 해야하는 경우이를 수행 할 수 있습니다.

$ vim test

#!/bin/bash
pwd
:wq to save the test file.

실행 권한을 부여하십시오.

chmod u+x test

그런 다음 스크립트를 실행하면 ./test현재 작업 디렉토리를 볼 수 있습니다.


2
문제는 스크립트가 작업 디렉토리 가 아닌 경우를 포함하여 자체 디렉토리 에서 스크립트가 실행되도록하는 방법이었습니다 . 따라서 이것은 답이 아닙니다. 어쨌든, 왜 그냥 달리는 대신에 이것을 합니까? 나에게 많은 키 누름이 낭비되는 것 같습니다. pwd
underscore_d
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.