Почему " cd " не работает в сценарии оболочки?
Я пытаюсь написать небольшой скрипт, чтобы изменить текущий каталог в каталог моего проекта:
#!/bin/bash
cd /home/tree/projects/java
Я сохранил этот файл как proj, добавил разрешение на выполнение с chmod, и скопировал его в /usr/bin. Когда я называю его:
proj, он ничего не делает. Что я делаю не так?
29 ответов:
сценарии оболочки выполняются внутри подрешетки, и каждая подрешетка имеет свое собственное представление о том, что такое текущий каталог. Элемент
cdуспешно, но как только подрешетка выйдет, вы вернетесь в интерактивную оболочку, и там ничего не изменится.один из способов обойти это использовать псевдоним:
alias proj="cd /home/tree/projects/java"
вы не делаете ничего плохого! Вы изменили каталог, но только в пределах подобласти, которая запускает сценарий.
вы можете запустить скрипт в текущем процессе с помощью команды" dot":
. projно я бы предпочел предложение Грега использовать псевдоним в этом простом случае.
The
cdв вашем скрипте технически работала как он изменил каталог оболочки, которая запускала скрипт, но это был отдельный процесс, разветвленный от вашей интерактивной оболочки.Posix-совместимый способ решить эту проблему-определить процедура раковины, а не оболочки-вызывается команды скрипта.
jhome () { cd /home/tree/projects/java }Вы можете просто ввести это или поместить его в один из различных файлов запуска оболочки.
The
cdвыполняется в оболочке скрипта. Когда сценарий заканчивается, эта оболочка выходит, а затем вы остаетесь в каталоге, в котором вы были. "Исходный" скрипт, не запускайте его. Вместо:./myscript.shdo
. ./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
когда вы запустите скрипт, он работает новая экземпляр этой оболочки (
/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/bashEDIT: это также может быть "пунктиром", чтобы предотвратить создание последующих оболочек.
пример:
. ./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"теперь запуск псевдонима проекта будет выполнять сценарий проекта в текущей оболочке, а не в подрешетке.
в ~/.файл 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 ..Сcddcdd() { 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