Ответ 1
bash --rcfile <(echo '. ~/.bashrc; some_command')
освобождает создание временных файлов. Вопрос на других сайтах:
Это должно быть действительно просто или очень сложно, но я ничего не мог найти об этом... Я пытаюсь открыть новый экземпляр bash, а затем запустить несколько команд внутри него и вернуть управление для пользователя внутри того же экземпляра.
Я пробовал:
$ bash -lic "some_command"
но это выполняет some_command
внутри нового экземпляра, затем закрывает его. Я хочу, чтобы он оставался открытым.
Еще одна деталь, которая может повлиять на ответы: если я смогу заставить это работать, я буду использовать ее в моем .bashrc
как псевдоним (es), поэтому бонусные баллы для реализации alias
!
bash --rcfile <(echo '. ~/.bashrc; some_command')
освобождает создание временных файлов. Вопрос на других сайтах:
Это поздний ответ, но у меня была одна и та же проблема, и google отправил меня на эту страницу, поэтому для полноты вот как я столкнулся с проблемой.
Насколько я могу судить, bash не имеет возможности делать то, что хотел сделать оригинальный плакат. Опция -c всегда будет возвращаться после выполнения команд.
Сломанное решение: простейшая и очевидная попытка:
bash -c 'XXXX ; bash'
Это частично работает (хотя и с дополнительным слоем подкласса). Однако проблема заключается в том, что, хотя суб-оболочка наследует экспортируемые переменные среды, псевдонимы и функции не наследуются. Таким образом, это может работать для чего-то, но не является общим решением.
Лучше: чтобы создать динамический файл запуска и вызвать bash с этим новым файлом инициализации, убедитесь, что ваш новый файл инициализации вызывает ваш обычный ~/.bashrc, если это необходимо.
# Create a temporary file
TMPFILE=$(mktemp)
# Add stuff to the temporary file
echo "source ~/.bashrc" > $TMPFILE
echo "<other commands>" >> $TMPFILE
echo "rm -f $TMPFILE" >> $TMPFILE
# Start the new bash shell
bash --rcfile $TMPFILE
Приятно, что временный файл инициализации удалит себя, как только он будет использован, уменьшая риск того, что он не будет правильно очищен.
Примечание. Я не уверен, что /etc/bashrc обычно называют частью обычной оболочки без входа. Если это так, вы можете захотеть указать источник /etc/bashrc, а также ваш ~/.bashrc.
Вы можете передать --rcfile
в Bash, чтобы заставить его читать файл по вашему выбору. Этот файл будет считан вместо вашего .bashrc
. (Если это проблема, источник ~/.bashrc
от другого script.)
Изменить:. Таким образом, функция запуска новой оболочки с материалом из ~/.more.sh
будет выглядеть примерно так:
more() { bash --rcfile ~/.more.sh ; }
... и в .more.sh
у вас будут команды, которые вы хотите выполнить при запуске оболочки. (Я полагаю, было бы элегантно избегать отдельного файла запуска - вы не можете использовать стандартный ввод, потому что тогда оболочка не будет интерактивной, но вы можете создать загрузочный файл из этого документа во временном месте, а затем прочитать его.)
Вы можете получить нужную функциональность, используя script вместо ее запуска. например:
$cat script cmd1 cmd2 $ . script $ at this point cmd1 and cmd2 have been run inside this shell
В соответствии с ответом daveraja, здесь есть сценарий bash, который решит цель.
Рассмотрим ситуацию, если вы используете C-shell и хотите выполнить команду, не выходя из контекста/окна C-shell, следующим образом:
Команда для выполнения: Поиск точного слова "Тестирование" в текущем каталоге рекурсивно только в файлах *.h, *.c
grep -nrs --color -w --include="*.{h,c}" Testing ./
Решение 1. Войдите в bash из C-shell и выполните команду
bash
grep -nrs --color -w --include="*.{h,c}" Testing ./
exit
Решение 2. Запишите нужную команду в текстовый файл и выполните ее, используя bash.
echo 'grep -nrs --color -w --include="*.{h,c}" Testing ./' > tmp_file.txt
bash tmp_file.txt
Решение 3: Запустите команду в той же строке, используя bash
bash -c 'grep -nrs --color -w --include="*.{h,c}" Testing ./'
Решение 4. Создайте sciprt (единовременно) и используйте его для всех будущих команд
alias ebash './execute_command_on_bash.sh'
ebash grep -nrs --color -w --include="*.{h,c}" Testing ./
Сценарий заключается в следующем,
#!/bin/bash
# =========================================================================
# References:
# https://stackoverflow.com/a/13343457/5409274
# https://stackoverflow.com/a/26733366/5409274
# https://stackoverflow.com/a/2853811/5409274
# https://stackoverflow.com/a/2853811/5409274
# https://www.linuxquestions.org/questions/other-%2Anix-55/how-can-i-run-a-command-on-another-shell-without-changing-the-current-shell-794580/
# https://www.tldp.org/LDP/abs/html/internalvariables.html
# https://stackoverflow.com/a/4277753/5409274
# =========================================================================
# Enable following line to see the script commands
# getting printing along with their execution. This will help for debugging.
#set -o verbose
E_BADARGS=85
if [ ! -n "$1" ]
then
echo "Usage: 'basename $0' grep -nrs --color -w --include=\"*.{h,c}\" Testing ."
echo "Usage: 'basename $0' find . -name \"*.txt\""
exit $E_BADARGS
fi
# Create a temporary file
TMPFILE=$(mktemp)
# Add stuff to the temporary file
#echo "echo Hello World...." >> $TMPFILE
#initialize the variable that will contain the whole argument string
argList=""
#iterate on each argument
for arg in "[email protected]"
do
#if an argument contains a white space, enclose it in double quotes and append to the list
#otherwise simply append the argument to the list
if echo $arg | grep -q " "; then
argList="$argList \"$arg\""
else
argList="$argList $arg"
fi
done
#remove a possible trailing space at the beginning of the list
argList=$(echo $argList | sed 's/^ *//')
# Echoing the command to be executed to tmp file
echo "$argList" >> $TMPFILE
# Note: This should be your last command
# Important last command which deletes the tmp file
last_command="rm -f $TMPFILE"
echo "$last_command" >> $TMPFILE
#echo "---------------------------------------------"
#echo "TMPFILE is $TMPFILE as follows"
#cat $TMPFILE
#echo "---------------------------------------------"
check_for_last_line=$(tail -n 1 $TMPFILE | grep -o "$last_command")
#echo $check_for_last_line
#if tail -n 1 $TMPFILE | grep -o "$last_command"
if [ "$check_for_last_line" == "$last_command" ]
then
#echo "Okay..."
bash $TMPFILE
exit 0
else
echo "Something is wrong"
echo "Last command in your tmp file should be removing itself"
echo "Aborting the process"
exit 1
fi
Добавьте к ~/.bashrc
раздел, подобный этому:
if [ "$subshell" = 'true' ]
then
# commands to execute only on a subshell
date
fi
alias sub='subshell=true bash'
Затем вы можете запустить подоболочку с помощью sub
.
Принятый ответ действительно полезен! Просто добавить, что подстановка процесса (т. <(COMMAND)
) не поддерживается в некоторых оболочках (например, dash
).
В моем случае я пытался создать пользовательское действие (в основном, однострочный сценарий оболочки) в файловом менеджере Thunar, чтобы запустить оболочку и активировать выбранную виртуальную среду Python. Моя первая попытка была:
urxvt -e bash --rcfile <(echo ". $HOME/.bashrc; . %f/bin/activate;")
где %f
- это путь к виртуальной среде, обрабатываемой Thunar. Я получил ошибку (запустив Thunar из командной строки):
/bin/sh: 1: Syntax error: "(" unexpected
Тогда я понял, что мой sh
(по существу, dash
) не поддерживает процесс подстановки.
Мое решение состояло в том, чтобы вызвать bash
на верхнем уровне для интерпретации подстановки процесса за счет дополнительного уровня оболочки:
bash -c 'urxvt -e bash --rcfile <(echo "source $HOME/.bashrc; source %f/bin/activate;")'
В качестве альтернативы я попытался использовать здесь документ для dash
но безуспешно. Что-то вроде:
echo -e " <<EOF\n. $HOME/.bashrc; . %f/bin/activate;\nEOF\n" | xargs -0 urxvt -e bash --rcfile
PS: У меня недостаточно репутации, чтобы оставлять комментарии, модераторы, пожалуйста, не стесняйтесь перемещать их в комментарии или удалять, если они не помогли с этим вопросом.