Изменить текущий каталог из скрипта Bash

133

Можно ли изменить текущий каталог из script?

Я хочу создать утилиту для навигации по каталогам в bash. Я создал тест script, который выглядит следующим образом:

#!/bin/bash
cd /home/artemb

Когда я выполняю script из оболочки bash, текущий каталог не изменяется. Возможно ли вообще изменить текущий каталог оболочки из script?

  • 0
    Просто предложение по улучшению: если вы используете pushd (возможно перенаправленный в >/dev/null для подавления вывода) вместо cd , вы можете позже вернуться в предыдущий каталог с помощью popd .
  • 0
    Возможный дубликат Почему "cd" не работает в скрипте оболочки bash?
Теги:
environment

11 ответов

134
Лучший ответ

Вам нужно преобразовать script в функцию оболочки:

#!/bin/bash
#
# this script should not be run directly,
# instead you need to source it from your .bashrc,
# by adding this line:
#   . ~/bin/myprog.sh
#

function myprog() {
  A=$1
  B=$2
  echo "aaa ${A} bbb ${B} ccc"
  cd /proc
}

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

Предоставляя вашей программе функцию оболочки, вы добавляете свою собственную команду in-process, а затем любое изменение каталога находит отражение в процессе оболочки.

  • 2
    как бы вы сделали это в tcsh?
  • 4
    +1. Одна вещь, которую я заметил, была в файле, мы должны определить функцию перед ее вызовом. Это может помочь кому-то так же неопытному, как я.
Показать ещё 4 комментария
157

При запуске script создается новый процесс, который только наследует вашу среду. Когда он заканчивается, он заканчивается. Ваша текущая среда остается такой, как есть.

Вместо этого вы можете запустить свой script следующим образом:

. myscript.sh

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

  • 2
    +1 потому что ты прав. Хотя я искренне сомневаюсь, что он захочет создавать сценарий изменения каталога каждый раз, когда ему это нужно. Кроме того, расширения .sh полностью eww. Не используйте их.
  • 1
    Да, обычно так лучше не использовать. Большую часть времени вы рады, что ваше нынешнее окружение не пострадает. Но затем у меня есть сценарии для выполнения некоторых задач по настройке для меня, включая переход в нужное место, а затем я. их тоже. Btw. .sh это, конечно, вопрос личного стиля. Я, вероятно, не использовал бы это при установке сценариев всей системы. Но в моем ~ / bin я использую их, чтобы знать, что к чему :)
Показать ещё 5 комментариев
43

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

  • добавьте script в PATH
  • запустите script как . scriptname

В . (точка) убедитесь, что script не запущен в дочерней оболочке.

29

Объединив выше, вы можете сделать псевдоним

alias your_cmd=". your_cmd"

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

  • 0
    Будет ли это сохраняться при перезагрузках?
  • 1
    @SDsolar Вы должны добавить это в файл ~ / .bashrc, чтобы сделать его постоянным. Работает как шарм для меня.
Показать ещё 2 комментария
25

Если вы используете bash, вы можете попробовать псевдоним:

в файл .bashrc добавьте эту строку:

alias p='cd /home/serdar/my_new_folder/path/'

когда вы пишете "p" в командной строке, он изменит каталог.

  • 1
    +1 для псевдонима. Функция оболочки интересна, но ОП попросил простую навигацию с помощью CD. Я предполагаю, что большинству людей нужен такой скрипт для навигации по веткам исходного кода, и для этого псевдонима достаточно
  • 1
    Я пробовал, но он говорит, что команда не найдена
Показать ещё 1 комментарий
14

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

Если цель заключается в выполнении вашей команды: goto.sh/home/test Затем интерактивно работать в /home/test одним способом - запустить интерактивную подоболочку bash в вашем script:

#!/bin/bash
cd $1
exec bash

Таким образом вы будете в /home/test, пока не выйдете (выйдите или Ctrl + C) этой оболочки.

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

С помощью pushd текущий каталог помещается в стек каталога, и он изменяется на данный каталог, popd получает каталог поверх стека и меняет его на он.

pushd ../new/dir > /dev/null
# do something in ../new/dir
popd > /dev/null
  • 2
    Это отвечает на мой вопрос - активное развертывание этого решения с помощью сценария инициализации S3, и оно прекрасно работает. Спасибо @seb.
4

Просто перейдите к

yourusername/.bashrc (or yourusername/.bash_profile on MAC) by an editor

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

alias yourcommand="cd /the_path_you_wish"

Затем закройте редактор.

Затем введите:

source ~/.bashrc or source ~/.bash_profile on MAC.

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

3

В основном мы используем cd.. для возврата из любого каталога. Я решил сделать это более легким, указав количество каталогов, с которыми вам нужно вернуться за раз. Вы можете реализовать это, используя отдельный файл script, используя команду alias. Например:

code.sh

#!/bin/sh
 _backfunc(){
 if [ "$1" -eq 1 ]; then
  cd ..
 elif [ "$1" -eq 2 ]; then
  cd ../..
 elif [ "$1" -eq 3 ]; then
  cd ../../..
 elif [ "$1" -eq 4 ]; then
  cd ../../../..
 elif ["$1" -eq 10]; then
  cd /home/arun/Documents/work
 fi
 }
alias back='_backfunc'   

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

$back 2 

чтобы вернуться на два шага назад из текущего каталога. Здесь подробно описано здесь. Также объясняется, как помещать код в ~/.bashrc, чтобы каждая новая оболочка открывала автоматически эту новую команду alias. Вы можете добавить новую команду, чтобы перейти к конкретным каталогам, изменив код, добавив больше if conditions и различные аргументы. Вы также можете вывести код из git поверх здесь.

  • 0
    Хорошее решение, так что вы никогда не испортите свой профиль bash :)
3

Я создал script для изменения каталога. посмотрите: https://github.com/ygpark/dj

0

Этот подход мне легче.

Предположим, что на личном iMac, где вы являетесь администратором, в каталоге по умолчанию, когда открывается окно команды, /Users/jdoe, это будет каталог, куда нужно перейти:/Users/jdoe/Desktop/Mongo/db. 3.2.1/бен.

Это шаги, которые могут быть выполнены: 1. vi mongobin, в который я ввел:   "cd/Users/jdoe/Desktop/Mongo/db.3.2.1/bin" в качестве первой строки. 2. chmod 755 монгобин 3. источник монгобинов 4. pwd

Voila!

Ещё вопросы

Сообщество Overcoder
Наверх
Меню