Скрипт для изменения текущей директории (cd, pwd)

44

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

#!/bin/bash
cd web/www/project

Но после того, как я запустил его, текущий pwd остается неизменным! Как я могу это сделать?

Sony Santos
источник

Ответы:

63

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

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

Для изменения каталога постоянно следует источник сценарий, как и в

. ./script
enzotib
источник
8
@Sony: Обратите внимание, что вы должны использовать returnдля выхода из сценария, полученного таким способом, а не exit- они похожи на функции оболочки и exitвыйдут из оболочки, которая создала сценарий.
Чарльз Стюарт
@CharlesStewart На самом деле, я не знаком с исходными текстами. Спасибо!
Sony Santos
5
такое source ./scriptже?
amyassin
2
@amyassin: да, это
энзотиб
2
1. .и sourceравны в баш. 2. нам не нужно использовать ./перед именем файла, если он находится в том же каталоге. Это нормально, чтобы запустить только это:. script
sobi3ch
19

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

$ alias cdproj='cd /dir/web/www/proj'

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

Теперь вы можете запустить это как $ cdproj.

Сачин Дивекар
источник
1
Сценарий также может отображать команды, которые должны быть выполнены, а затем использовать eval `./script` или eval $(./script)для выполнения этих команд. Это общий подход для команд, которым необходимо обновить среду вызывающей оболочки.
Кит Томпсон
2
Просто будьте очень осторожны с тем, что вы выводите, если вы собираетесь пойти на evalподход.
jw013
13

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

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

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

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

#!/usr/bin/env bash
cd desired/directory
exec bash

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

Серж Строобандт
источник
Лучше просто написать сценарий, как в принятом ответе: использование execобычно считается последним средством негодяя .. :)
нейросеть
1
этот трюк не работает в Debian 9 Stretch.
августа
3
Это неправильный путь!
Приостановлено до дальнейшего уведомления.
4
Поскольку никто не детализировал проблемы с этим (я смотрю на вас, @Dennis): (1) Каждый раз, когда вы запускаете это, он создает новый, постоянный процесс bash. Сделайте это десять или двадцать раз за сессию, и у вас будет от 11 до 21 процессов bash. Это может повлиять на производительность, и, если вы попытаетесь аккуратно завершить сеанс, набрав exit(или Ctrl + D), вам придется делать это 11–21 раз. (2) Другой недостаток использования исполняемого скрипта состоит в том, что если вы установите какие-либо параметры оболочки (например,  dotglobили  globstar) в сеансе интерактивной оболочки, вы потеряете их, потому что запускаете новую оболочку.
G-Man говорит: «Восстанови Монику»
1
Очень хорошее решение! Я переписал свой псевдоним в bash_profile, так что теперь это скрипт, который хранится в отдельном файле. Я использую скрипт для перехода во вновь созданную временную папку. А теперь еще проще иметь временную сессию bash. SRP в действии! Благодарность!
Артём.разинов
8

Хотя есть ответы, которые выполняют именно то действие, которое вы хотите, более стандартным методом для этой цели является создание символической ссылки:

ln -s ~/web/www/project proj   #use full path to dir!

Тогда вы можете cdв каталог, используя имя proj:

cd proj

Этот метод более гибкий, потому что вы можете получить доступ к файлам, используя короткое имя без cd:

ls proj/   #note the endslash!
vim proj/file.x
Корвин
источник
4

Если вы переключаетесь между каталогами далеко в файловой системе. Я буду рекомендовать AutoJump .

stnly
источник
4

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

Пример:

Создайте функцию в файле, скажем /home/aidin/my-cd-script:

function my-cd() {
  cd /to/my/path
}

Затем включите его в свой файл bashrcили zshrcфайл:

# Somewhere in rc file
source /home/aidin/my-cd-script

Теперь вы можете использовать его как команду:

$ my-cd
Помощь в
источник
0

Почему бы не использовать «exec», чтобы сделать именно то, что я хочу.

#!/bin/bash

cd someplace
exec bash

~/someplace
Павел
источник
1
Остерегайтесь вещей, которые, кажется, то, что вы хотите. (Гигантская деревянная лошадь! Как раз то, что я хотел!) Каждый раз, когда вы запускаете это, он создает новый, постоянный процесс bash. Сделайте это десять или двадцать раз за сеанс, и у вас будет от 11 до 21 процессов bash. Это может повлиять на производительность, и, если вы попытаетесь аккуратно завершить сеанс, набрав exit(или Ctrl + D), вам придется делать это 11–21 раз.
G-Man говорит: «Восстанови Монику»
Я определенно мог видеть, где это было бы проблемой. Для меня, хотя я использую это один раз, делаю работу, в которой нуждаюсь, и затем ухожу. Если это единственный недостаток, я могу жить с этим. С другой стороны, если есть лучшее решение, я хочу посмотреть на него.
Пол
Ответ Айдина на этот вопрос с использованием функции оболочки и ответ Сачина Дивекара с использованием псевдонима (IMO) являются лучшими решениями, чем использование сценария. PS Еще один недостаток использования скрипта заключается в том, что, если вы установите какие-либо параметры оболочки (например,  dotglobили  globstar), вы потеряете их, потому что запускаете новую оболочку. … (Продолжение)
G-Man говорит «Восстановить Монику»
(Продолжение)… PPS Я только что заметил, что вы, в основном, повторяете ответ Сержа Стробандта и говорите: «Почему бы не сделать это?» На  Stack Exchange мы ожидаем, что ответы предоставят новые идеи и / или информацию, а не просто обсудят другие ответы.
G-Man говорит: «Восстанови Монику»
-1

Вы можете сделать это с помощью функции или с помощью &&. Примеры ниже устанавливают Zabbix и создают файл со строкой внутри него.

Пример:

#!/bin/bash

# Create Function:
installZabbix(){
    cd /usr/src/zabbix-4.2.4;
    ./configure --enable-agent;
    make install;
    cd /usr/src/;
    >file;
    echo "Hi, this is a file." >>file;
}

# Call the function:
installZabbix

или:

#!/bin/bash
cd /usr/src/zabbix-4.2.4 && ./configure --enable-agent && make install && cd /usr/src && >file && echo "Hi, this is a file." >>file
Рауль Кьярелла
источник