it-roy-ru.com

Почему "cd" не работает в сценарии оболочки?

Я пытаюсь написать небольшой скрипт, чтобы изменить текущий каталог на каталог моего проекта:

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

Я сохранил этот файл как proj, добавил разрешение на выполнение с chmod и скопировал его в /usr/bin. Когда я называю это: proj, он ничего не делает. Что я делаю неправильно?

656
ashokgelal

Сценарии оболочки запускаются внутри подоболочки, и каждая подоболочка имеет свою концепцию текущего каталога. cd завершается успешно, но как только завершается работа подоболочки, вы возвращаетесь в интерактивную оболочку и ничего там не меняется.

Один из способов обойти это, вместо этого использовать псевдоним:

alias proj="cd /home/tree/projects/Java"
555
Greg Hewgill

Вы не делаете ничего плохого! Вы изменили каталог, но только внутри подоболочки, которая запускает скрипт.

Вы можете запустить скрипт в текущем процессе с помощью команды "точка":

. proj

Но я бы предпочел, чтобы Грег предложил использовать псевдоним в этом простом случае.

438
Adam Liss

cd в вашем сценарии технически сработала так как изменила каталог оболочки, в которой выполнялся сценарий, но это был отдельный процесс, раздвоенный от вашей интерактивной оболочки.

Совместимый с Posix способ решения этой проблемы состоит в том, чтобы определить процедуру Shell , а не вызываемую Shell командный сценарий .

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

Вы можете просто ввести это или поместить в один из различных файлов запуска Shell.

205
DigitalRoss

cd выполняется в оболочке скрипта. Когда сценарий заканчивается, эта оболочка завершается, и вы остаетесь в том каталоге, в котором находились. «Исходный» сценарий, не запускайте его. Вместо:

./myscript.sh

делать

. ./myscript.sh

(Обратите внимание на точку и пробел перед именем скрипта.)

135
Tzachi.e

Чтобы создать скрипт bash, который перейдет в выбранный каталог:

Создать файл скрипта

 #!/bin/sh 
 # file: /scripts/cdjava
#
cd /home/askgelal/projects/Java

Затем создайте псевдоним в вашем файле запуска.

 #!/bin/sh 
 # file /scripts/mastercode.sh
#
alias cdjava = '. /scripts/cdjava'

  • Я создал файл автозагрузки, куда я выгружаю все свои псевдонимы и пользовательские функции .
  • Затем я отправляю этот файл в свой .bashrc, чтобы он устанавливался при каждой загрузке .

Например, создайте основной файл псевдонимов/функций: /scripts/mastercode.sh
(Поместите псевдоним в этот файл.)

Тогда в конце вашего .bashrc файл:

 source /scripts/mastercode.sh



Теперь легко перейти в ваш каталог Java, просто наберите cdjava, и вы там.

90
Matt Thomas

Идея Джереми Рутена об использовании символической ссылки вызвала мысль, которая не нашла никакого другого ответа. Использование:

CDPATH=:$HOME/projects

Ведущая толстая кишка важна; это означает, что если в текущем каталоге есть каталог «dir», то «cd dir» изменится на него, а не прыгнет куда-то еще. С установленным значением, как показано, вы можете сделать:

cd Java

и, если в текущем каталоге нет подкаталога с именем Java, то вы попадете прямо в $ HOME/projects/Java - без псевдонимов, без скриптов, без сомнительных команд или точечных команд.

Мой $ 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
36
Jonathan Leffler

Вы можете использовать . для выполнения скрипта в текущей среде Shell:

. script_name

или, альтернативно, его более читаемый, но специфичный для Shell псевдоним source:

source script_name

Это позволяет избежать подоболочки и позволяет любым переменным или встроенным функциям (включая cd) влиять на текущую оболочку.

33
Astha

Я получил свой код для работы с помощью . <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$ 
25
kaelhop

Используйте exec bash в конце

Скрипт bash работает в своей текущей среде или в своей дети, но никогда не в родительской среде.

Однако этот вопрос часто задают, потому что кто-то хочет остаться в приглашении bash в определенном каталоге после выполнения сценария bash из другого каталога.

Если это так, просто запустите дочерний экземпляр bash в конце скрипта:

#!/bin/bash
cd /home/tree/projects/Java
exec bash
18
Serge Stroobandt

просто запустите:

cd /home/xxx/yyy && command_you_want
17
warhansen

Когда вы запускаете сценарий оболочки, он запускает новый экземпляр этой оболочки (/bin/bash). Таким образом, ваш скрипт просто запускает оболочку, меняет каталог и завершает работу. Другими словами, cd (и другие подобные команды) в сценарии оболочки не влияют и не имеют доступа к оболочке, из которой они были запущены.

11
Daniel Spiewak

В моем конкретном случае мне нужно было слишком много раз переходить на один и тот же каталог. Итак, на моем .bashrc (я использую Ubuntu) я добавил 

1 -

$ nano ~./bashrc

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

2- 

$ source ~/.bashrc

3 - 

$ switchp Java

Непосредственно это будет делать: cd/home/tree/projects/Java

Надеюсь, это поможет!

9
workdreamer

Вы можете сделать следующее:

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

Правка: Это также может быть «пунктирной», чтобы предотвратить создание последующих оболочек.

Пример:

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

Вы можете объединить псевдоним и скрипт,

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

при условии, что скрипт повторяет путь назначения. Обратите внимание, что это обратные ссылки, окружающие имя скрипта.

Например, ваш скрипт может быть

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

Преимущество этого метода заключается в том, что сценарий может принимать любое количество параметров командной строки и выдавать различные пункты назначения, рассчитанные, возможно, сложной логикой.

7
J. A. Faucett

Это только изменяет каталог для самого скрипта, в то время как ваш текущий каталог остается прежним.

Возможно, вы захотите использовать символическую ссылку вместо. Это позволяет вам сделать «ярлык» для файла или каталога, так что вам нужно всего лишь напечатать что-то вроде cd my-project.

7
Jeremy Ruten

для быстрой навигации по каталогам, есть $ CDPATH, cdargs и способы автоматической генерации псевдонимов

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

5
Gene T

Вы можете комбинировать псевдонимы и точки доступа Адама и Грега, чтобы сделать что-то более динамичное -

alias project=". project"

Теперь при запуске псевдонима проекта будет выполняться сценарий проекта в текущей оболочке, а не подоболочка. 

5
mogga

В вашем файле ~/.bash_profile. добавить следующую функцию

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

Перезапустите терминал, и вы можете ввести

move_me 

и вы будете перемещены в папку назначения.

3
mihai.ciorobea

Хотя поиск сценария, который вы хотите запустить, является одним из решений, вы должны знать, что этот сценарий может напрямую изменить среду вашей текущей оболочки. Также невозможно передавать аргументы.

Другой способ сделать это - реализовать ваш скрипт как функцию в bash.

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

Этот метод используется autojump: http://github.com/joelthelion/autojump/wiki , чтобы обеспечить вас изучением закладок каталога Shell.

3
thomasd

Это должно делать то, что вы хотите. Перейдите в каталог, представляющий интерес (из скрипта), а затем создайте новую оболочку bash.

#!/bin/bash

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

Если вы запустите это, то вы попадете в интересующий каталог, а когда вы выйдете из него, вы вернетесь в исходное место.

[email protected]:~# ./mov_dir.sh

[email protected]:~/mt/v3/rt_linux-rt-tools# exit
[email protected]:~#

Это даже приведет вас к исходному каталогу при выходе (CTRL+d)

3
jithu83

Вы можете использовать оператор &&:

cd myDirectory && ls

3
Jack Bauer

Через некоторое время, но я сделал следующее:

создать файл с именем case

вставьте в файл следующее:

#!/bin/sh

cd /home/"$1"

сохраните это и затем:

chmod +x case

Я также создал псевдоним в своем .bashrc:

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

теперь, когда я печатаю:

case 12345

по сути, я печатаю:

cd /home/12345

Вы можете напечатать любую папку после 'case':

case 12

case 15

case 17

что похоже на набор:

cd /home/12

cd /home/15

cd /home/17

соответственно

В моем случае путь намного длиннее - эти парни суммировали его с ~ информацией ранее.

2
chris

Вы можете создать функцию, как показано ниже в вашем .bash_profile, и она будет работать без сбоев.

Следующая функция принимает необязательный параметр, который является проектом . Например, вы можете просто запустить

cdproj

или же

cdproj project_name

Вот определение функции.

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

Не забудьте указать свой .bash_profile

1
Krish

Вам не нужен скрипт, только установите правильную опцию и создайте переменную окружения.

shopt -s cdable_vars

в вашем ~/.bashrc позволяет cd к содержимому переменных окружения.

Создайте такую ​​переменную среды:

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

и вы можете использовать:

cd myjava

Другие альтернативы .

0
Gauthier

Если вы используете fish в качестве оболочки, лучшее решение - создать функцию. В качестве примера, учитывая исходный вопрос, вы можете скопировать 4 строки ниже и вставить их в командную строку вашей рыбы:

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

Это создаст функцию и сохранит ее для последующего использования. Если ваш проект изменяется, просто повторите процесс, используя новый путь.

Если вы предпочитаете, вы можете вручную добавить файл функции, выполнив следующие действия:

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

и введите текст:

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

и, наконец, нажмите Ctrl + X, чтобы выйти, а затем Y, чтобы сохранить изменения.

(ПРИМЕЧАНИЕ: первый метод использования funcsave создает файл proj.fish для вас).

0
Lane Roathe

У меня есть простой сценарий bash под названием p для управления изменением каталога
github.com/godzilla/bash-stuff
Просто поместите скрипт в локальный каталог bin (/ usr/local/bin)
и положи

alias p='. p'

в вашем .bashrc 

0
godzilla

Использование функций профиля Bash:

Одной из особенностей профиля bash является сохранение пользовательских функций, которые можно запускать в терминале или в сценариях bash, так же, как вы запускаете приложение/команды, это также можно использовать в качестве ярлыка для длинных команд. 

Чтобы ваша система работала эффективно, вам нужно будет скопировать свою функцию в конце нескольких файлов.

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

Вы можете Sudo kwrite /home/user/.bashrc /home/user/.bash_profile /root/.bashrc /root/.bash_profile быстро редактировать/создавать эти файлы

Пример скрипта

Создание ярлыка для cd .. с помощью cdd

cdd() {
  cd ..
}

лс ярлык

ll() {
  ls -l -h
}

лс ярлык

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

Как :

Скопируйте свою функцию в конце ваших файлов и перезагрузите терминал, после чего вы можете запустить cdd или любую другую функцию, которую вы написали.

0
intika

Обратите внимание на обсуждение Как мне установить рабочий каталог родительского процесса?

Он содержит несколько хакерских ответов, например, __. https://stackoverflow.com/a/2375174/755804 (изменение каталога родительского процесса через gdb, не делайте этого) и https: // stackoverflow .com/a/51985735/755804 (команда tailcd, которая внедряет cd dirname во входной поток родительского процесса; в идеале она должна быть частью bash, а не хаком)

0
18446744073709551615