Почему “CD” не работает в сценарии оболочки?

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

Я поместил ниже команд в файле /home/alex/pathABC

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

Я сделал chmod +x pathABC.

В терминале, в то время как в /home/alex, Я работаю ./pathABC, но вывод справедлив HelloWorld и текущий каталог не изменяется.

Так что не так?

60
задан 24 July 2018 в 14:05

8 ответов

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

Несколько альтернатив:

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. Избегайте запуска в качестве дочернего

Создайте сценарий вместо запуска. При использовании источника (выполняется . или исходным кодом ) сценарий выполняется в той же оболочке, а не в собственной подоболочке.

$ . ./pathABC

(из здесь и здесь )

5. cd -able vars

Установите параметр cdable_vars в вашем ~ / .bashrc и создайте переменную среды в каталоге:

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

Затем вы можете использовать cd pathABC

(из здесь )

91
ответ дан 23 November 2019 в 00:01

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

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

9
ответ дан 23 November 2019 в 00:01

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

Вы можете увидеть это, создав другой сценарий в новом ] и запускать его из вашего сценария после смены каталога:

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

Второй сценарий будет запускаться из нового каталога.

HelloWorld 

- это просто результат выполнения сценария.

6
ответ дан 23 November 2019 в 00:01

Потому что hello world - это просто инструкция трассировки , давайте попробуем следующее:

Создайте файл сценария bash cd.sh , содержащий:

#!/bin/bash
echo "/home/mike/Documents/A/B/C"
  • Расширение .sh - это старое соглашение о присвоении расширению имен файлов сценариев bash. Это чисто косметический вид и обычно не нужен. Однако в этом случае важно отличаться от команды core 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 отправляется обратно в parent через $ (...) . Родитель (приглашение нашей оболочки) использует этот вывод и передает его команде Linux cd .

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

0
ответ дан 23 November 2019 в 00:01

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

Для изменения каталога используйте источник. Вы можете либо используйте . scriptname.sh или source scriptname.sh , чтобы использовать источник.

Примечание: Также, когда вы используете источник, не используйте команду выхода, потому что тогда она закрывает ваше соединение.

0
ответ дан 5 January 2021 в 23:07

CDPATH может помочь в некоторых случаях.

# add this to .bashrc .zshrc or whatever
export CDPATH="/home/alex/Documents/A/B:$CDPATH"

# and then you can just do...
cd C

Обратите внимание, вы должны добавить «A / B» к CDPATH, а не «A / B / C» Вы можете добавить несколько путей к CDPATH, как и PATH.

0
ответ дан 5 January 2021 в 23:07

На самом деле, после многих поисков я только что обнаружил, что если вам нужно сменить каталог и по-прежнему сохранить ту же оболочку, вы получите все ответы в своем текущем сценарий, вы можете использовать:

(cd your_dir; do_some_command_there)

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

((cd your_dir; git remote -v | wc -l)

Работает как шарм!

1
ответ дан 5 January 2021 в 23:07

Параметры доступности KDE появляется возможность начать ORCA на загрузку.

KDE Accessibility Options

-121--913215-

Использование $ Shell в конце

скрипт Bash работает на его текущей среде или на его Дети, но никогда не в родительской среде.

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

Если это так, просто Exection Exmain $ Shell в конце скрипта:

# !/usr/bin/env bash
cd /home/alex/Documents/A/B/C
echo -e '\nHit [Ctrl]+[D] to exit this child shell.'
$SHELL

Чтобы вернуться к предыдущему экземпляру Ratemental Shell, используйте Ctrl + D .

0
ответ дан 2 April 2021 в 00:50

Другие вопросы по тегам:

Похожие вопросы: