Как написать на bash программу (исполнимый файл), которая меняет каталог?
Хочу написать скрипт на bash, который помимо прочего должен сменить текущий каталог. Затем хочу сделать этот скрипт исполняемым, написать вначале shebang и поместить в папку, находящуюся в моём $PATH, чтобы вызывать из любого места.
Однако при попытке сделать это столкнулся с тем, что каталог не меняется, т. к. этот скрипт вызывается в отдельном интерпретаторе (в shebang написал #!/bin/bash).
Как же написать программу, меняющую текущий каталог (если это возможно О_о)?
Вариант сделать скрипт функцией и добавить в .bashrc не нравится, т. к. .bashrc выполняется перед запуском интерпретатора и таким образом увеличивает время ожидания при каждом запуске терминала. Поэтому задача поставлена именно так. Меня интересует теоретическая сторона вопроса.
UPD
Уточнение вопроса:
- требуется создать ИСПОЛНИМЫЙ ФАЙЛ
- этот самый ИСПОЛНИМЫЙ ФАЙЛ предполагается положить в одну из папок PATH и вызывать откуда угодно в терминале
- ИСПОЛНИМЫЙ ФАЙЛ при вызове самостоятельно завершать работу и менять текущую рабочую директорию
- ИСПОЛНИМЫЙ ФАЙЛ должен быть написан на bash (и быть с необходимым в этом случае shebang'ом, как я полагаю)
UPD2
Последнее условие (ИСПОЛНИМЫЙ ФАЙЛ должен быть написан на bash) не критично.
И не надо объяснять мне, как решить ту практическую задачу, в ходе которой возникла эта, теоретическая.
нет, в том-то и дело, что это не работает. Если сделать скрипт исполняемым файлом и запустить как программу (на самом деле даже если запустить как bash ), то он начинает работать в отдельном интерпретаторе и как только его работа заканчивается, рабочая папка меняется на ту, которая была до запуска.
То, что вы хотите, по-хорошему решается не так, как вы хотите.
Но если настолько сильно хочется странного - то пример гуглится в первой же ссылке.
Обвязку для того, как выцепить PID родителя, напишите сами. unix.stackexchange.com/questions/281994/changing-t...
То, что вы хотите, по-хорошему решается не так, как вы хотите.
А как то что я хочу решается по-хорошему?
Сейчас мне больше всего нравится вариант написать скрипт и создать алиас alias myscript='. myscript'
Но если настолько сильно хочется странного - то пример гуглится в первой же ссылке.
Какой поисковый запрос вы использовали?
Обвязку для того, как выцепить PID родителя, напишите сами.
Оказывается, это просто $PPID в bash
Т. е. получается
#!/bin/bash
cwd="$1" # the target working directory
# now let's command the GNU debugger
gdb -q &> /dev/null <<EOF
attach $PPID
call (int) chdir("$cwd")
detach
quit
EOF
После запуска этот скрипт действительно меняет рабочий каталог процесса интерпретатора, но не меняет "внутренний" каталог оболочки bash, то есть:
- программы вроде ls и /bin/pwd запускаются в каталоге процесса и показывают новую директорию
- внутренние команды вроде pwd и cd и переменная $PWD ведут себя так, будто директория не менялась. Приглашение остаётся прежним (если оно настроено на отображение рабочего каталога)
Не могу сказать, что это не то, что я просил, т. к. не уточнил, что имел ввиду ещё и смену каталога внутри окружения.
Но на самом деле мне была интересна также и смена каталога внутри окружения.
Отсюда ещё вопросы:
Мы смогли изменить рабочий каталог процесса по его PID.
- Нет ли в bash какой-то внутренней возможности заставить его сверять рабочий каталог своего процесса с рабочим каталогом оболочки? (например после выполнения каждой команды)
- Нет ли в bash возможности заставить вместе с каждым выводом приглашения выполнять какую-то команду [нууу, например PWD="$(/bin/pwd)"]
- Можно ли сделать с процессом что-то ТАКОЕ, что когда ТАКОЕ происходит с интерпретатором bash, это заставляет его сверить и синхронизировать свой рабочий каталог как процесса и рабочий каталог как шелла в пользу первого?
- Можно ли направить стандартный вывод программы на стандартный ввод какого-то процесса [интерпретатора bash] по его PID без предварительной подготовки со стороны этого процесса?
ЗЫ: - можно ли сделать то же самое без gdb и других "внешних" программ, т. е. средствами оболочки или более "стандартных" внешних команд? А то это выглядит как пальба из пушки по воробьям.
Вариант сделать скрипт функцией и добавить в .bashrc не устраивает, т. к., во-первых, .bashrc выполняется перед запуском интерпретатора и таким образом при его удлинении увеличивается время ожидания при каждом запуске терминала
1) Нет не замечу. Меня полностью устраивает решение добавить такую функцию в bashrc. Но оно не является ответом на это вопрос. Речь идёт о том, чтобы программа в моём окружении могла менять рабочий каталог и была написана на bash.
2) Если скрипт очень большой и таких скриптов много, то увеличение времени ожидания может стать заметным.
3) увеличение в .bashrc увеличивает время ожидания => такая постановка задачи
Свою практическую задачу я уже решил. Меня интересует теоретическая.
Нет, не лабораторная, у меня возникла практическая задача, в ходе которой мне стало интересно это.
Открыл этот ман, ничего понятного для себя не нашёл, т. к. он видимо рассчитан на тех, кто уже понимает, что такое "процесс" и описывает функции языка C.
6elkka: Ну так гуглите, что такое "процесс". Или Вы думаете, что тут Вам будут рассказывать? C и UNIX - близнецы-братья :) разумеется, это ман на функцию языка C - а Вы думаете, bash на чем написан?
> требуется создать ИСПОЛНИМЫЙ ФАЙЛ
> этот самый ИСПОЛНИМЫЙ ФАЙЛ предполагается положить в одну из папок PATH и вызывать откуда угодно в терминале
> ИСПОЛНИМЫЙ ФАЙЛ при вызове самостоятельно завершать работу и менять текущую рабочую директорию
Это невозможно. Ну или по крайней мере не должно быть возможно без использования весьма развесистых костылей типа программной записи на ввод телетайпа.
Рабочий каталог — это свойство окружения процесса и он точно так же, как и все окружение, наследуется дочерними процессами, а не разделяется с ними. А исполняемый файл по определению исполняется в дочернем процессе.
Об этом уже писали, но почему-то этот ответ пропал. Строго говоря, это не совсем то, спрашивается. Но всё равно спасибо за участие ;)
На практике я именно так и сделал, создав алиас alias tt='. tt'