난 내가 뭘 할 수 있는지 알아껍데기또는스크립트를 실행하는 대신 가져오기cd
내가 사용하는 쉘 에 . 내가 알고 싶은 건 바로 거기에 있어어느"상위 쉘"로 이동합니다 cd
(올바른 문구인지 확실하지 않음).
#!/bin/sh
# This is script.sh
cd $1
pwd
다음은 몇 가지 결과입니다. (노트:정확한 출력은 아니고, 불필요한 부분을 제거해서 짧게 만들었습니다. 내가 쉘에 입력한 줄은 >
. )
> mkdir foo
> ./script.sh foo
/home/myName/foo
> pwd
/home/myName
내가 이해하는 한 이는 예상되는 동작입니다. 이것이 내가 스크립트를 "얻을" 때 일어나는 일입니다.
> . ./script.sh foo
/home/myName/foo
> pwd
/home/myName/foo
스크립트를 가져와서 이를 쉘 프로시저로 만들지 않고 ./script.sh foo
디렉토리에 사용되는 쉘에 결과를 입력 할 수 있는 방법이 있습니까 /home/myName/foo
?
답변1
아니요. 스크립트를 으로 호출하면 ./script.sh foo
스크립트를 실행하는 하위 쉘이 시작되기 때문입니다. 서브쉘이 종료되면 스크립트를 시작한 디렉토리로 돌아갑니다. 그러나 다음을 수행하는 스크립트를 사용하여 이 동작을 가짜로 만들 수 있습니다.
#!/bin/bash
cd $1
bash
디렉터리를 변경한 후 하위 쉘로 이동한 다음 exit
원래 쉘로 돌아가야 합니다.
마지막 줄로 변경하는 경우:
exec bash
새 셸이 이전 셸을 대체하므로 새 셸을 종료할 필요가 없습니다. 그러나 이렇게 하는 것은 여전히 추악한 해킹입니다(IMHO).
답변2
간단한 대답은 '아니요'입니다. 불가능합니다.
그러나 절망적이라면 몇 가지 해결 방법을 찾을 수 있습니다.
가장 쉬운 방법은 몇 개의 디렉토리만 필요한 경우입니다.미리 알아두세요(상위 셸에서) 스크립트가 cd
입력을 시도할 수 있는 위치입니다. 이 경우 스크립트에서 전송된 특정 신호에 대한 트랩을 설정할 수 있습니다.
~ $ cat script
#!/bin/bash
kill -s SIGINT "$PPID"
~ $ trap 'cd /tmp' SIGINT
~ $ ./script
/tmp $
이를 수행하는 보다 정교한 방법은 스크립트의 명령을 상위 쉘의 표준 입력에 작성하는 것입니다. 절차를 설명합니다(다소 복잡함).여기, 그러나 가장 간단한 경우(디렉토리를 미리 정의하는 경우)도 간단합니다.
~ $ cat script
#!/bin/bash
printf '\e[5n' >/proc/"$PPID"/fd/0
~ $ bind '"\e[0n": "cd /tmp\n"'
~ $ ./script
/tmp $
스크립트에서 상위 셸로 디렉터리 이름을 매개변수로 전달하려면 위 링크에서 답변을 살펴보는 것이 좋습니다.
답변3
당신은 시도 할 수 있습니다:
gdb --batch -ex 'call chdir("/some/dir")' -p "$PPID"
그러나 현재 디렉토리가 변경되면 대부분의 쉘이 혼란스러워질 것으로 예상됩니다.
그런데 쉘 구문에서는 변수 주위에 따옴표를 넣고 --
옵션과 인수를 구분해야 합니다. cd
실패 시 특수 동작 도 참조하세요 -P
. 따라서 코드는 다음과 같아야 합니다.
#! /bin/sh -
cd -P -- "$1"
예: int main(int argc, char*argv[]){chdir(argv[1])}
C 언어에 해당(다른 프로세스의 현재 디렉터리를 변경할 때 여전히 효과가 없음)
답변4
스크립트는 서브셸에서 실행되며 모든 환경 변경 사항(디렉터리 및 변수)은 해당 프로세스에 로컬이며 프로세스가 종료되거나 제어권을 되돌릴 때 호출 프로세스의 환경 변경 사항으로 되돌아갑니다.
명령을 실행할 수 있습니다현재 쉘에서(그래서 그 효과는 여전히 지속됩니다) 스크립트( . here/is/the/script
)를 얻거나 쉘 함수를 정의함으로써. 셸 기능은 매우 복잡할 수 있으며 가장 중요한 것은 현재 셸 프로세스 내에서 실행된다는 것입니다. 모든 쉘이 기능을 지원하는 것은 아닙니다(bash는 지원합니다).