Programing

쉘 스크립트에서 "cd"가 작동하지 않는 이유는 무엇입니까?

lottogame 2020. 9. 30. 08:34
반응형

쉘 스크립트에서 "cd"가 작동하지 않는 이유는 무엇입니까?


현재 디렉터리를 내 프로젝트 디렉터리로 변경하는 작은 스크립트를 작성하려고합니다.

#!/bin/bash
cd /home/tree/projects/java

이 파일을 proj로 저장하고로 실행 권한을 추가 chmod한 다음 /usr/bin. 으로 호출하면 proj아무것도하지 않습니다. 내가 도대체 ​​뭘 잘못하고있는 겁니까?


쉘 스크립트는 서브 쉘 내에서 실행되며 각 서브 쉘에는 현재 디렉토리가 무엇인지에 대한 고유 한 개념이 있습니다. cd성공하지만 곧 서브 쉘 종료, 당신은있는 대화 형 쉘 다시 아무것도 이제까지이 변경되었습니다.

이 문제를 해결하는 한 가지 방법은 대신 별칭을 사용하는 것입니다.

alias proj="cd /home/tree/projects/java"

당신은 잘못한 것이 없습니다! 디렉토리를 변경했지만 스크립트를 실행하는 서브 쉘 내에서만 가능합니다.

"dot"명령을 사용하여 현재 프로세스에서 스크립트를 실행할 수 있습니다.

. proj

그러나 저는이 간단한 경우에 별칭을 사용하는 Greg의 제안을 선호합니다.


cd스크립트에서 기술적으로 작동 이 스크립트를 실행 한 쉘의 디렉토리를 변경으로,하지만 대화 형 쉘에서 포크 별도의 프로세스이었다.

이 문제를 해결하기위한 Posix 호환 방법 은 쉘 호출 명령 스크립트가 아닌 쉘 프로 시저 를 정의하는 입니다.

jhome () {
  cd /home/tree/projects/java
}

이것을 입력하거나 다양한 쉘 시작 파일 중 하나에 넣을 수 있습니다.


cd스크립트의 쉘 내에서 수행된다. 스크립트가 종료되면 해당 셸이 종료되고 이전 디렉토리에 남아 있습니다. 스크립트를 "소스"로 지정하고 실행하지 마십시오. 대신에:

./myscript.sh

하다

. ./myscript.sh

(스크립트 이름 앞의 점과 공백에 유의하십시오.)


선택 디렉토리로 이동하는 bash 스크립트를 작성하려면 다음을 수행하십시오.

스크립트 파일 만들기

#! / bin / sh
# 파일 : / scripts / cdjava
#
cd / home / askgelal / projects / java

그런 다음 시작 파일에 별칭을 만듭니다.

#! / bin / sh
# 파일 /scripts/mastercode.sh
#
별칭 cdjava = '. / scripts / cdjava '

  • 모든 별칭과 사용자 지정 함수를 덤프하는 시작 파일을 만들었습니다.
  • 그런 다음이 파일을 .bashrc로 가져 와서 부팅 할 때마다 설정합니다.

예를 들어, 마스터 별칭 / 함수 파일을 만듭니다. /scripts/mastercode.sh
(이 파일에 별칭을 입력합니다.)

그런 다음 .bashrc 파일 의 끝에서 :

소스 /scripts/mastercode.sh



이제 Java 디렉토리로 쉽게 이동할 수 있습니다. cdjava를 입력하면됩니다.


.현재 셸 환경에서 스크립트를 실행하는 데 사용할 수 있습니다 .

. script_name

또는 더 읽기 쉽지만 셸 별 별칭 source:

source script_name

이것은 서브 쉘을 피하고 모든 변수 또는 내장 (포함 cd)이 대신 현재 쉘에 영향을 미칠 수 있도록합니다 .


제레미 루텐 (Jeremy Ruten)의 심볼릭 링크 사용 아이디어는 다른 답을 넘지 못한 생각을 촉발 시켰습니다. 사용하다:

CDPATH=:$HOME/projects

선행 콜론이 중요합니다. 즉, 현재 디렉토리에 'dir'디렉토리가 있으면 cd dir다른 곳에서 벗어나지 않고 ' '이 해당 디렉토리로 변경됩니다. 표시된대로 값을 설정하면 다음을 수행 할 수 있습니다.

cd java

현재 디렉토리에 java라는 하위 디렉토리가 없으면 $ HOME / projects / java로 직접 이동합니다. 별칭, 스크립트, 모호한 execs 또는 도트 명령이 없습니다.

내 $ HOME은 / Users / jleffler입니다. 내 $ CDPATH는 다음과 같습니다.

:/Users/jleffler:/Users/jleffler/mail:/Users/jleffler/src:/Users/jleffler/src/perl:/Users/jleffler/src/sqltools:/Users/jleffler/lib:/Users/jleffler/doc:/Users/jleffler/work

사용하여 작업 할 코드가 있습니다.. <your file name>

./<your file name> 터미널에서 디렉토리를 변경하지 않기 때문에 작동하지 않습니다. 단지 해당 스크립트에 특정한 디렉토리 만 변경합니다.

내 프로그램입니다

#!/bin/bash 
echo "Taking you to eclipse's workspace."
cd /Developer/Java/workspace

여기 내 터미널입니다

nova:~ Kael$ 
nova:~ Kael$ . workspace.sh
Taking you to eclipe's workspace.
nova:workspace Kael$ 

사용 exec bash마지막에

bash 스크립트는 현재 환경 또는 하위 환경에서 작동하지만 상위 환경에서는 작동하지 않습니다.

그러나이 질문 은 다른 디렉토리에서 bash 스크립트를 실행 한 후 특정 디렉토리의 (새로운) bash 프롬프트에 남아 있기를 원 하기 때문에 자주 묻는 질문 입니다.

이 경우 스크립트 끝에서 자식 bash 인스턴스실행 하면됩니다.

#!/usr/bin/env bash
cd /home/tree/projects/java
exec bash

간단히 실행 :

cd /home/xxx/yyy && command_you_want

셸 스크립트를 실행하면 해당 셸 인스턴스 ( /bin/bash)가 실행됩니다. 따라서 스크립트는 쉘을 실행하고 디렉토리를 변경 한 후 종료됩니다. 달리 말하면 cd, 쉘 스크립트 내의 (및 기타 그러한 명령)은 실행 된 쉘에 영향을주지 않으며 액세스 할 수 없습니다.


다음을 수행 할 수 있습니다.

#!/bin/bash
cd /your/project/directory
# start another shell and replacing the current
exec /bin/bash

편집 : 후속 쉘 생성을 방지하기 위해 '점선'이 될 수도 있습니다.

예:

. ./previous_script  (with or without the first line)

내 특별한 경우에는 동일한 디렉토리를 변경하는 데 너무 많은 시간이 필요했습니다. 그래서 내 .bashrc (나는 우분투 사용)에

1 -

$ 나노 ~. / bashrc

 function switchp
 {
    cd /home/tree/projects/$1
 }

2-

$ 소스 ~ / .bashrc

삼 -

$ switchp 자바

직접 수행합니다 : cd / home / tree / projects / java

도움이 되었기를 바랍니다.


현재 디렉토리는 그대로 유지되는 동안 스크립트 자체의 디렉토리 만 변경합니다.

You might want to use a symbolic link instead. It allows you to make a "shortcut" to a file or directory, so you'd only have to type something like cd my-project.


You can combine an alias and a script,

alias proj="cd \`/usr/bin/proj !*\`"

provided that the script echos the destination path. Note that those are backticks surrounding the script name. 

For example, your script could be

#!/bin/bash
echo /home/askgelal/projects/java/$1

The advantage with this technique is that the script could take any number of command line parameters and emit different destinations calculated by possibly complex logic.


You can combine Adam & Greg's alias and dot approaches to make something that can be more dynamic—

alias project=". project"

Now running the project alias will execute the project script in the current shell as opposed to the subshell.


to navigate directories quicky, there's $CDPATH, cdargs, and ways to generate aliases automatically

http://jackndempsey.blogspot.com/2008/07/cdargs.html

http://muness.blogspot.com/2008/06/lazy-bash-cd-aliaes.html

https://web.archive.org/web/1/http://articles.techrepublic%2ecom%2ecom/5100-10878_11-5827311.html


In your ~/.bash_profile file. add the next function

move_me() {
    cd ~/path/to/dest
}

Restart terminal and you can type

move_me 

and you will be moved to the destination folder.


You can use the operator && :

cd myDirectory && ls


While sourcing the script you want to run is one solution, you should be aware that this script then can directly modify the environment of your current shell. Also it is not possible to pass arguments anymore.

Another way to do, is to implement your script as a function in bash.

function cdbm() {
  cd whereever_you_want_to_go
  echo "Arguments to the functions were $1, $2, ..."
}

This technique is used by autojump: http://github.com/joelthelion/autojump/wiki to provide you with learning shell directory bookmarks.


This should do what you want. Change to the directory of interest (from within the script), and then spawn a new bash shell.

#!/bin/bash

# saved as mov_dir.sh
cd ~/mt/v3/rt_linux-rt-tools/
bash

If you run this, it will take you to the directory of interest and when you exit it it will bring you back to the original place.

root@intel-corei7-64:~# ./mov_dir.sh

root@intel-corei7-64:~/mt/v3/rt_linux-rt-tools# exit
root@intel-corei7-64:~#

This will even take you to back to your original directory when you exit (CTRL+d)


LOOOOOng time after, but I did the following:

create a file called case

paste the following in the file:

#!/bin/sh

cd /home/"$1"

save it and then:

chmod +x case

I also created an alias in my .bashrc:

alias disk='cd /home/; . case'

now when I type:

case 12345

essentially I am typing:

cd /home/12345

You can type any folder after 'case':

case 12

case 15

case 17

which is like typing:

cd /home/12

cd /home/15

cd /home/17

respectively

In my case the path is much longer - these guys summed it up with the ~ info earlier.


You can create a function like below in your .bash_profile and it will work smoothly.

The following function takes an optional parameter which is a project. For example, you can just run

cdproj

or

cdproj project_name

Here is the function definition.

cdproj(){
    dir=/Users/yourname/projects
    if [ "$1" ]; then
      cd "${dir}/${1}"
    else
      cd "${dir}"
    fi
}

Dont forget to source your .bash_profile


Using Bash Profile Functions :

One feature of the bash profile is to store custom functions that can be run in the terminal or in bash scripts the same way you run application/commands this also could be used as a shortcut for long commands.

To make your function efficient system widely you will need to copy your function at the end of several files

/home/user/.bashrc
/home/user/.bash_profile
/root/.bashrc
/root/.bash_profile

You can sudo kwrite /home/user/.bashrc /home/user/.bash_profile /root/.bashrc /root/.bash_profile to edit/create those files quickly

Script Example

Making shortcut to cd .. with cdd

cdd() {
  cd ..
}

ls shortcut

ll() {
  ls -l -h
}

ls shortcut

lll() {
  ls -l -h -a
}

Howto :

Copy your function at the end of your files and reboot your terminal you can then run cdd or whatever the function you wrote


If you are using fish as your shell, the best solution is to create a function. As an example, given the original question, you could copy the 4 lines below and paste them into your fish command line:

function proj
   cd /home/tree/projects/java
end
funcsave proj

This will create the function and save it for use later. If your project changes, just repeat the process using the new path.

If you prefer, you can manually add the function file by doing the following:

nano ~/.config/fish/functions/proj.fish

and enter the text:

function proj
   cd /home/tree/projects/java
end

and finally press ctrl+x to exit and y followed by return to save your changes.

(NOTE: the first method of using funcsave creates the proj.fish file for you).


I have a simple bash script called p to manage directory changing on
github.com/godzilla/bash-stuff
just put the script in your local bin directory (/usr/local/bin)
and put

alias p='. p'

in your .bashrc


You need no script, only set the correct option and create an environment variable.

shopt -s cdable_vars

in your ~/.bashrc allows to cd to the content of environment variables.

Create such an environment variable:

export myjava="/home/tree/projects/java"

and you can use:

cd myjava

Other alternatives.


Note the discussion How do I set the working directory of the parent process?

It contains some hackish answers, e.g. https://stackoverflow.com/a/2375174/755804 (changing the parent process directory via gdb, don't do this) and https://stackoverflow.com/a/51985735/755804 (the command tailcd that injects cd dirname to the input stream of the parent process; well, ideally it should be a part of bash rather than a hack)


You can execute some lines in the same subshell if you end lines with backslash.

cd somedir; \
pwd

참고URL : https://stackoverflow.com/questions/255414/why-doesnt-cd-work-in-a-shell-script

반응형