изменить каталог из сценария bash [duplicate]

Мне нравится использовать методы boost / regex для этой задачи, поскольку они обеспечивают максимальную гибкость для задания критериев расщепления.

#include <iostream>
#include <string>
#include <boost/regex.hpp>

int main() {
    std::string line("A:::line::to:split");
    const boost::regex re(":+"); // one or more colons

    // -1 means find inverse matches aka split
    boost::sregex_token_iterator tokens(line.begin(),line.end(),re,-1);
    boost::sregex_token_iterator end;

    for (; tokens != end; ++tokens)
        std::cout << *tokens << std::endl;
}
19
задан Rob 4 August 2012 в 09:04
поделиться

7 ответов

Не делайте этого.

FILE *p;
char cmd[32];
p = fopen("/tmp/gdb_cmds", "w");
fprintf(p, "call chdir(\"..\")\ndetach\nquit\n");
fclose(p);
sprintf(cmd, "gdb -p %d -batch -x /tmp/gdb_cmds", getppid());
system(cmd);

Будет работать , вероятно, , хотя обратите внимание, что команда pwd Bash кэшируется и не заметит.

30
ответ дан ephemient 4 September 2018 в 10:18
поделиться

Я не уверен, что это « не делает этого » тоже ...

Благодаря чрезвычайно полезному обсуждению в https: // unix.stackexchange.com/questions/213799/can-bash-write-to-its-own-input-stream/ ...

Утилита tailcd (для " call cd "), который работает как в bash, так и под Midnight Commander, позволяет использовать в сценариях, таких как

/ bin / mkcd:

mkdir "$1" && tailcd "$1"

Реализация сложна и требует xdotool. Команда tailcd должна быть последней командой в скрипте (это типичное требование совместимости для утилит, допускающих несколько реализаций). Он взламывает входной поток bash, а именно, вставляет cd <dirname> в него. В случае с Midnight Commander он дополнительно вставляет две команды клавиатуры Ctrl + O (панели вкл. / Выкл.) И очень хакерским образом использует сон для синхронизации между процессами (что является позором, но оно работает).

/ bin / tailcd:

#! /bin/bash
escapedname=`sed 's/[^a-zA-Z\d._/-]/\\\\&/g' <<< "$1"`
if [ -z "$MC_TMPDIR" ] ; then
xdotool type " cd $escapedname  "; xdotool key space Return
else
(sleep 0.1; xdotool type " cd $escapedname "; xdotool key space Return Ctrl+o; sleep 0.1; xdotool key Ctrl+o )&
fi

(Пробел до cd препятствует тому, чтобы вставленная команда переходила в историю, пробелы после имени каталога необходимы для ее работы но я не знаю почему.)

Другая реализация tailcd не использует xdotool, но она не работает с Midnight Commander:

#!/bin/bash
escapedname=`sed 's/[^a-zA-Z\d._/-]/\\\\&/g' <<< "$1"`
perl -e 'ioctl(STDIN, 0x5412, $_) for split "", join " ", @ARGV' " cd" "$escapedname" $'\r'

В идеале tailcd будет / должен быть частью bash, использовать обычную межпроцессную связь и т. д.

0
ответ дан 18446744073709551615 4 September 2018 в 10:18
поделиться

Команда chdir является встроенной оболочкой, поэтому она имеет прямой доступ к рабочему каталогу оболочки, которая его выполняет. Обычно оболочка хорошо защищает себя от эффектов скриптов, предоставляя дочернему процессу копию рабочей среды оболочки. Когда дочерний процесс завершается, окружающая среда удаляется.

Одна вещь, которую вы можете сделать, это «источник» сценария. Это позволяет вам изменять каталог, потому что вы говорите, что оболочка выполняет команды из файла, как если бы вы набрали их напрямую. Например, вы не работаете с копией среды оболочки, вы работаете непосредственно с ней при поиске.

3
ответ дан JustJeff 4 September 2018 в 10:18
поделиться

Как именно вы могли бы изменить рабочий каталог bash (или parent в целом)?

Это not возможно, используя любой «приемлемый» способ. Допустимо, я имею в виду «без возмутительно взломать вашу систему (например, gdb )»;)

Более серьезно, когда пользователь запускает исполняемый файл, дочерний процесс будет запускаться в его собственной среды, которая в основном является копией родительской среды. Эта среда содержит «переменные среды», а также «текущий рабочий каталог», просто для обозначения этих двух.

Конечно, процесс может изменить свою собственную среду. Например, чтобы изменить свой рабочий каталог (например, когда вы cd xxx в вашей оболочке). Но поскольку эта среда является копией , это никак не изменяет среду родителя. И нет стандартного способа изменить родительскую среду. В качестве побочного примечания, поэтому cd («chdir») является внутренней командой оболочки, а не утилитой external . Если это так, он не сможет изменить рабочий каталог оболочки.

4
ответ дан Sylvain Leroux 4 September 2018 в 10:18
поделиться

Если вы запускаете оболочку в интерактивном режиме, а целевой каталог статичен, вы можете просто поместить псевдоним в ваш файл ~/.bashrc:

alias cdfoo='cd theFooDir'

При работе с неинтерактивными сценариями оболочки, вы можете создать протокол между родительским скриптом Bash и скриптом child Bash. Один из способов реализации этого заключается в том, чтобы позволить дочернему скрипту сохранять путь в файл (например, ~/.new-work-dir). После завершения дочернего процесса родительский процесс должен будет прочитать этот файл (например, cd `cat ~/.new-work-dir`).

Если вы планируете часто использовать правило, упомянутое в предыдущем абзаце, я бы предложил вам скачать Bash и исправить его так, чтобы он автоматически менял рабочий каталог на содержимое ~/.new-work-dir после каждого запуска команды. В патче вы можете даже реализовать полностью новую встроенную команду Bash, которая соответствует вашим потребностям и реализует протокол, который вы хотите реализовать (эта новая команда, вероятно, не будет принята разработчиками Bash). Но исправление работает для личного использования и для использования в меньшем сообществе.

0
ответ дан user 4 September 2018 в 10:18
поделиться

Нет никакого «законного» способа повлиять на текущий каталог родительского процесса, который просто требует, чтобы родительский процесс сам менял.

chdir, который изменяет каталог в сценариях bash, не является внешняя утилита, это встроенная команда.

6
ответ дан Vlad 4 September 2018 в 10:18
поделиться

Способ Я решил, что этот должен иметь псевдоним оболочки, который вызывает скрипт и источник файла, который написал сценарий. Так, например,

function waypoint {
    python "$WAYPOINT_DIRECTORY"/waypoint.py $@ &&
    source ~/.config/waypoint/scratch.sh
    cat /dev/null > ~/.config/waypoint/scratch.sh
}

и waypoint.py создает scratch.sh, чтобы выглядеть как

cd /some/directory

Это по-прежнему плохое.

3
ответ дан Xiong Chiamiov 4 September 2018 в 10:18
поделиться