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



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



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


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

984   29  

29 ответов:

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

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

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

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

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

. proj

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

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

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

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

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

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

./myscript.sh

do

. ./myscript.sh

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

чтобы сделать сценарий bash, который будет cd в выбранном каталоге:

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

#!/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 file:

source /scripts/mastercode.sh



теперь его легко cd в каталог java, просто введите cdjava, и вы там.

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

CDPATH=:$HOME/projects

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

cd java

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

Мой $дома /пользователи/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

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

. script_name

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

source script_name

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

Я получил код для работы с помощью. <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 в конце скрипта:

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

просто наберите:

cd /home/xxx/yyy && command_you_want

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

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

1 -

$ nano ~./ bashrc

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

2-

$ source ~/.bashrc

3 -

$ switchp java

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

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

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

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

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

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

EDIT: это также может быть "пунктиром", чтобы предотвратить создание последующих оболочек.

пример:

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

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

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

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

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

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

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

чтобы быстро перемещаться по каталогам, есть $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

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

alias project=". project"

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

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

cd myDirectory & & ls

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

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

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

move_me 

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

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

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

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

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

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

#!/bin/bash

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

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

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

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

это даже приведет вас обратно в исходный каталог при выходе (CTRL+d)

LOOOOOng время после, но я сделал следующее:

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

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

#!/bin/sh

cd /home/""

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

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

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

в моем случае путь намного длиннее - эти ребята суммировали его с ~ info ранее.

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

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

cdproj

или

cdproj project_name

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

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

Не забудьте источник .bash_profile

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

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.рыбный файл для вас).

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

alias p='. p'

в свой .bashrc

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

shopt -s cdable_vars

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

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

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

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

cd myjava

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

Использование Функций Профиля 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
}

Howto:

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

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

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

вы можете выполнить несколько строк в той же подрешетке, если вы заканчиваете строки с обратной косой чертой.

cd somedir; \
pwd

Comments

    Ничего не найдено.