Змініть поточний каталог із сценарію Bash


190

Чи можна змінити поточний каталог зі сценарію?

Я хочу створити утиліту для навігації по каталогу в Bash. Я створив тестовий сценарій, який виглядає наступним чином:

#!/bin/bash
cd /home/artemb

Коли я виконую скрипт із оболонки Bash, поточний каталог не змінюється. Чи взагалі можливо змінити поточний каталог оболонки зі скрипту?


2
Просто пропозиція щодо вдосконалення: якщо ви використовуєте pushd(можливо, переспрямовано на >/dev/nullпридушення її виводу) замість cd, ви можете пізніше повернутися до попереднього каталогу popd.
mklement0

Відповіді:


173

Вам потрібно перетворити свій скрипт у функцію оболонки:

#!/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" вбудовані в інтерпретатор оболонки, щоб вони впливали на процес оболонки.

Здійснюючи вашу програму функцією оболонки, ви додаєте власну команду в процесі, а потім будь-яка зміна каталогу відображається в процесі оболонки.


2
як би ти це зробив у тчш?
joedborg

4
+1. Одне, що я помітив у файлі, ми повинні визначити функцію, перш ніж викликати її. Це може допомогти комусь так само недосвідченому, як я.
Бхушань

Яка велика різниця між визначенням функції та створенням псевдоніма?
HelloGoodbye

1
Як тільки я створив цей файл myprog.sh і додав його до .bashrc, як запустити сценарій? Чи повинен я викликати свою функцію з іншого файлу оболонки або безпосередньо з оболонки? Здається, це не працює ні в якому разі ...
Андреа Сільвестрі

1
@AndreaSilvestri Або вийдіть із системи та увійдіть назад або введіть джерело .bashrc. Додавання його до .bashrc нічого не робить, поки не запущено .bashrc.
Джон Страйер

214

Коли ви запускаєте сценарій, створюється новий процес, який успадковує лише ваше оточення. Коли він закінчується, він закінчується. Ваше поточне оточення залишається таким, яким воно є.

Натомість ви можете запустити сценарій так:

. myscript.sh

.Оцінюватиме сценарій в поточній середовищі, тому він може бути змінений


4
+1, тому що ти маєш рацію. Хоча я щиро сумніваюся, що він захоче створити сценарій зміни каталогів кожного разу, коли йому це потрібно. Більше того, .shрозширення є повністю eww. Не використовуйте їх.
lhunath

1
Так, зазвичай це краще не використовувати таким чином. Більшу частину часу ви раді, що ваше поточне оточення не страждає. Але тоді у мене є сценарії, щоб виконати деякі завдання налаштування для мене, включаючи зміну в потрібне місце, а потім я. їх теж. Btw. .sh, звичайно, питання особистого стилю. Я, мабуть, не використовував би його під час установки сценаріїв у всій системі. Але в моєму ~ / bin я використовую їх, щоб знати, що це таке :)
Норберт Хартл

11
@lhunath Чому розширення .sh є повністю eww?
Карл Притчетт


1
Для мене міркування в цій статті є хибними. Здається, результат був відомий наперед, але знайти його причини було не так просто. Тож я вважаю, що це питання особистого стилю, нічого іншого.
Норберт Хартл

55

Зважаючи на нечитабельність та надскладність відповідей, я вважаю, що саме це повинен зробити запитувач

  1. додати цей сценарій до PATH
  2. запустити сценарій як . scriptname

.(Точка) буде переконатися , що сценарій не виконується в дитячій оболонки.


38

Зібравши вищезгадане, ви можете скласти псевдонім

alias your_cmd=". your_cmd"

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


Чи залишиться це наполегливим через перезавантаження?
SDsolar

1
@SDsolar Вам потрібно додати це у файл ~ / .bashrc, щоб зробити його стійким. Працює як шарм для мене.
Rafał G.

Може бути поставлений у ~ / .bash_aliases
Чемпіон

@Champ ~/.bash_aliasesне завжди відбувається, коли Bash запускається.
Матеуш Піотровський

31

Якщо ви використовуєте bash, ви можете спробувати псевдонім:

у файл .bashrc додайте цей рядок:

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

коли ви пишете "p" в командному рядку, це змінить каталог.


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

19

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

Якщо мета - запустити вашу команду: goto.sh / home / test Тоді працюйте інтерактивно в / home / test, один із способів - запустити bash інтерактивну підпакет в рамках вашого сценарію:

#!/bin/bash
cd $1
exec bash

Таким чином, ви будете знаходитись у / home / test, поки не вийдете (вихід або Ctrl + C) цієї оболонки.


Я думав, що це виправить проблему для сценарію оболонки, який я виконував, але замість цього він запускає оболонку і забуває, що я хотів.
vwvan

13

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

pushd ../new/dir > /dev/null
# do something in ../new/dir
popd > /dev/null

2
Це відповідає на моє запитання - активно розгортаючи це рішення в сценарії S3 init, і воно працює чудово. Дякуємо @seb.
19ч

5

Просто перейдіть до

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.. для повернення з кожного каталогу. Я думав зробити це простіше, надавши кількість каталогів, з якими вам потрібно повернутися за раз. Ви можете реалізувати це за допомогою окремого файлу сценарію за допомогою команди 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, щоб кожна нова відкрита оболонка автоматично мала цю нову команду псевдоніму. Ви можете додати нову команду для переходу до конкретних каталогів, змінивши код, додавши ще if conditionsй різні аргументи. Ви також можете витягнути код з git тут .


Приємне рішення, тому ви ніколи не
псуєте

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 mongobin
  3. source mongobin
  4. pwd

Вуаля!


0

Я також створив утиліту під назвою коза, яку ви можете використовувати для легшої навігації.

Ви можете переглянути вихідний код на GitHub .

За V2.3.1 на оглядовому використання виглядає наступним чином :

# Create a link (h4xdir) to a directory:
goat h4xdir ~/Documents/dev

# Follow a link to change a directory:
cd h4xdir

# Follow a link (and don't stop there!):
cd h4xdir/awesome-project

# Go up the filesystem tree with '...' (same as `cd ../../`):
cd ...

# List all your links:
goat list

# Delete a link (or more):
goat delete h4xdir lojban

# Delete all the links which point to directories with the given prefix:
goat deleteprefix $HOME/Documents

# Delete all saved links:
goat nuke

# Delete broken links:
goat fix

0

Мені подобається робити те саме для різних проектів, не розпалюючи нову оболонку.

У вашому випадку:

cd /home/artemb

Збережіть сценарій як:

echo cd /home/artemb

Потім підпаліть його:

\`./the_script\`

Потім ви потрапляєте в каталог за допомогою тієї ж оболонки.




0

Просто напишіть PWDта експортуйте його всередині свого сценарію, і зміни зберігатимуться.

export PWD=/your/desired/directory
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.