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

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

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

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

Ответ 1

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

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

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

Ответ 2

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

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

. proj

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

Ответ 3

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

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

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

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

Ответ 4

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

./myscript.sh

делать

. ./myscript.sh

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

Ответ 5

Чтобы сделать bash script, который будет cd в каталоге выбора:

Создайте файл script

#!/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 и вы там.

Ответ 6

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

CDPATH=:$HOME/projects

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

cd java

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

My $HOME - это/Пользователи/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

Ответ 7

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

. script_name

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

source script_name

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

Ответ 8

Я получил свой код для работы с помощью . <your file name>

./<your file name> Доза не работает, потому что она не меняет ваш каталог в терминале, это просто изменяет каталог, специфичный для этого script.

Вот моя программа

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

Вот мой терминал

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

Ответ 9

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

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

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

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

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

Ответ 10

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

cd /home/xxx/yyy && command_you_want

Ответ 11

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

Ответ 12

Вы можете выполнить следующие действия:

#!/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)

Ответ 13

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

1 -

$nano ~./bashrc

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

2-

$source ~/.bashrc

3 -

$switchp java

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

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

Ответ 15

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

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

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

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

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

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

Ответ 17

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

alias project=". project"

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

Ответ 18

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

cd myDirectory && Ls

Ответ 19

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

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

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

move_me 

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

Ответ 20

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

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

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

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

Ответ 21

Это должно делать то, что вы хотите. Перейдите в каталог, представляющий интерес (из скрипта), а затем создайте новую оболочку 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)

Ответ 22

LOOOOOng после этого, но я сделал следующее:

создать файл с именем 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

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

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

Ответ 23

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

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

cdproj

или же

cdproj project_name

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

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

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

Ответ 25

Если вы используете 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).

Ответ 26

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

alias p='. p'

в вашем .bashrc

Ответ 27

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

shopt -s cdable_vars

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

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

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

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

cd myjava

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

Ответ 28

Использование функций профиля 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 для 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 или любую cdd функцию, которую вы написали.

Ответ 29

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

Он содержит некоторые хакерские ответы, например fooobar.com/questions/133653/... (изменение каталога родительского процесса с помощью GDB, не делайте этого) и fooobar.com/questions/133653/... ( команда tailcd которая внедряет имя tailcd диска во входной поток родительского процесса; в идеале это должна быть часть bash, а не хак)

Ответ 30

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

cd somedir; \
pwd