Чому "CD" не працює в сценарії оболонки?


43

Я просто хочу написати сценарій, який змінює мій каталог .

Я поклав команди нижче /home/alex/pathABC

#!/bin/sh
cd /home/alex/Documents/A/B/C
echo HelloWorld

Я так і зробив chmod +x pathABC.

У терміналі, перебуваючи в /home/alex, я запускаю ./pathABC, але вихід справедливий HelloWorldі поточний каталог не змінюється.

Отже, що не так?


Відповіді:


74

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

Кілька альтернатив:

1. Символічне посилання

Поставте символічне посилання у вашому домі на довгий шлях, до якого ви хочете легко дістатися

$ ln -s /home/alex/Documents/A/B/C ~/pathABC

потім перейдіть до каталогу за допомогою:

$ cd ~/pathABC

2. Псевдонім

Поставте псевдонім у своєму ~ / .bashrc:

alias pathABC="cd /home/alex/Documents/A/B/C"

( звідси )

3. Функція

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

( звідси )

4. Уникайте бігу як дитина

Джерело сценарію замість запуску. Sourcing (виконаний .або source) спричиняє виконання сценарію в одній оболонці замість запуску в його власній підпакеті.

$ . ./pathABC

( звідси і звідси )

5. cd-здатні вари

Встановіть cdable_varsпараметр у своєму ~/.bashrcі створіть змінну середовища для каталогу:

shopt -s cdable_vars
export pathABC="/home/alex/Documents/A/B/C"

Тоді можна використовувати cd pathABC

( звідси )


15
Тепер я розумію використання source! Мені завжди було цікаво, чому я це роблю, source .bashrcа ніbash .bashrc
hytromo

Варіант 3 спрацював чудово. Я щойно визначив функцію go_to_wherever () {cd my / directory} на початку мого сценарію. Викликав його перед запуском операцій у цьому каталозі.
i2097i

> 5. CD-здатний vars - чи не так cd $pathABC?
loxaxs

7

Під час запуску сценарію в терміналі запускається дочірній процес. У цій дочірній програмі, тобто ваш сценарій буде змінено на будь-який вказаний каталог. Але в батьківському процесі, тобто там, де ви запускаєте скрипт, все ще є старий шлях. АЛЕ просто ми можемо сказати:

The scope of cd command is only for child process not parent


2
Додавши до цього, @alex, щоб досягти ефекту, який ви шукаєте, виконайте скрипт у батьківському процесі, вибравши його: або . pathABCабо source pathABC.
zwets

4

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

Це можна побачити, створивши інший скрипт у новому каталозі та запустивши його зі свого сценарію після того, як він змінив каталог:

#!/bin/sh
cd /home/alex/Documents/A/B/C && ./another_script.sh # (if it is executable)

Другий сценарій запускається з нового каталогу.

HelloWorld 

- лише вихід сценарію.


3
HelloWorld не «повертається» до батьківської оболонки, він виводиться на стандартний вихід
Mog

Можливо, буде зрозуміліше, якщо ви просто запустите pwdв новій теці, замість того, щоб додати в ситуацію зовсім новий сценарій.
wjandrea

0

Оскільки привіт світ - це лише констатація сліду, спробуємо це:

Створіть файл bash script, cd.shщо містить:

#!/bin/bash
echo "/home/mike/Documents/A/B/C"
  • .shРозширення старої конвенції дає Баш скрипт для імен файлів розширення. Це чисто косметично і зазвичай непотрібно. Однак у цьому випадку важливо відрізнятись від основної cdкоманди.

Позначте файл виконавчого сценарію bash за допомогою:

chmod a+x cd.sh

Тепер запустіть файл:

$ cd $(./cd.sh)
bash: cd: /home/alex/Documents/A/B/C: No such file or directory
  • cd ми всі знаємо.
  • $(...) виконує команду всередині дужок і повертає результат.
  • Якщо cd.shу вас був шлях, вам не потрібно вказувати, де він знаходиться. Префікс із ./зазначенням команди знаходиться в поточному каталозі.
  • echoВихід з cd.shсценарію відправляється назад до батьків через $(...). Батько (наш підказки оболонки) використовує цей вихід і передає його cdкоманді Linux .

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


@wjandrea Ось що ви отримуєте за кодування по телефону! Щойно повернувшись додому, я це виправлю. Дякую. Гм щойно перевірений, і він працює чудово. Може це ваша 14.04версія, яку я прочитав близько години тому чи так?
WinEunuuchs2Unix

Ну, ви повністю змінили сценарій. Раніше це була лише одна команда:, cd /home/mike/Documents/A/B/Cяка не дала жодного результату. Тепер це echo "/home/mike/Documents/A/B/C", що робить випуск продукції.
wjandrea

@wjandrea Щоправда, я також повністю змінив спосіб виклику сценарію теж. Замість простого ./cd.shце зараз, cd $(./cd.sh)але він виконує мету дитини змінити поточний каталог батьків. Так, це нетрадиційно, але я сподіваюся, що людям це цікаво.
WinEunuuchs2Unix
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.