Source csh from bash
Существует возможность использовать файлы csh из среды bash. Идея простая: при выполнении файла командой source необходимые изменения касаются в первую очередь переменных текущей среды. Все остальные изменения (содержимого файлов, разрешений, настроек) не связаны с состоянием текущей оболочки. Значит можно сравнить состояние любой среды до и после применения файла, и сделать необходимые изменения.
Сразу отмечу, для загрузки используется родная оболочка, поэтому для иморта csh в bash, оболочка tcsh всё-равно нужна.
Рассмотрим три оболочки: bash, tcsh и fish
Contents
1. Отслеживание изменения переменных среды
Тут всё просто, надо выполнить diff для команды env до и после применения исходника. При этом любые вложенные вызовы source тоже обработаются корректно, как и все остальные команды. Скрипт автоматически определяет тип оболочки по расширению.
#!/bin/sh function filter (){ /bin/grep -vE "(^[^\+-]|^\+\+\+|^---|^[\+-]_|^[\+-]PIPESTATUS|^[\+-]COLUMNS)" } test "$*" || exit 1 case "$1" in *.sh) /bin/bash -c "diff -u <(env | sort) <(source $1 1>&2 ; env | sort)" | filter ;; *.csh|*.tcsh) /bin/tcsh -c "env | sort >/tmp/s_s1; source $1 ; env | sort>/tmp/s_s2; diff -u /tmp/s_s1 /tmp/s_s2" | filter rm /tmp/s_s[12]>/dev/null ;; *.fish) /usr/bin/fish -c "diff -u (env | sort | psub) (. $1 >&2 ; env | sort | psub)" | filter ;; *) echo Unknown source type $1 ;; esac
2. Импорт в текущую оболочку
Импорт происходит уже при помощи команды source текущей оболочке.
bash
В ~/.bashrc добавляем следующие функции:
- Для замены вывода команды diff. "+ENV=env" на "export ENV env", "-ENV" на "unset ENV"
bashimport () { sed "s/^-\([^=]\+\)=.\+\$/unset \1/; s/^+/export /;" }
ssource () { source <(sourceload $1 | bashimport) }
Использование:
ssource source_me.csh ssource source_me.fish
tcsh
Насколько я знаю, в tcsh нет функций, поэтому придётся обойтись source-файлом:
alias cshdifffilter 'sed "s/^-\([^=]\+\)=.\+/unsetenv \1/; s/^+/setenv /; s/=/ /g"' setenv file /tmp/cshimport.csh sourceload $1 | cshdifffilter > $file source $file rm $file
Используются так:
source /path/to/ssource.csh source_me.sh source /path/to/ssource.csh source_me.fish
В файле ~/.tcshrc можно создать алиасы (но я не проверял):
alias ssource "source /path/to/ssource.csh $1"
fish
В fish нету команды source, т.ч. её можно смело подменить:
function source --description 'Source fish/sh/csh file' for file in $argv switch $file case \*.fish . $file case \*.sh \*.csh \*.tcsh sourceload $file | fishimport case \* echo Unknown source type $file end end end
С импортом немного сложнее. Дело в том, что fish проверяет существование путей, добавляемых в PATH, поэтому надо перестраховаться:
function fishimport --description 'Import env diff' set -l pattern "s/^-\([^=]\+\)=.\+\$/set -e \1/; s/^+/set -gx /; s/=/ /g; s/:/ /g" set -l patternP "s/^[-+]PATH=//; s/:/ /g" while read line set -l sub (expr substr "$line" 1 5) test "$sub" = "-PATH"; and continue if test "$sub" = "+PATH" eval set line (echo $line | sed $patternP) for pt in $line if not contains $pt $PATH set -gx PATH $PATH $pt ^/dev/null; or echo "Unable to add '$pt' to \$PATH. Check existance." end end continue end echo $line | sed $pattern | . end end
Использование:
source source_me.sh source source_me.csh source source_me.fish
User:MaximGonchar 11:29, 2 November 2010 (MSK)