Хорошо, я написал сценарий оболочки для чтения файла в формате:
ярлык1 /путь/к/каталогу1
ярлык2 /путь/к/каталогу2
и предполагается, что он будет читать файл и создавать псевдонимы таким образом, что при вводе ярлыка <cd> я попадаю в сопоставленный каталог. Проблема в том, что любой из псевдонимов, заданных в цикле, не сохраняется вне скрипта.
Сначала я попытался просто запустить скрипт.
. ./build_shortcuts.sh "~/.shortcuts"
где файл ~/.shortcuts содержит
dl ~/Downloads
music /music
dtop ~/Desktop
Это не сработало. Затем я попытался установить некоторые псевдонимы вне цикла. Например, псевдоним hello='world'; псевдоним world='hellob'. Я перезапустил сценарий, набрал alias, чтобы получить список псевдонимов, и он включал в себя hello и world как псевдонимы, но не какие-либо из установленных в цикле.
Затем я подумал, что, возможно, цикл вообще их не устанавливает, поэтому я добавил псевдоним в качестве последней команды в скрипте, чтобы в конце он распечатывал псевдонимы; в этом случае он включал псевдонимы, но они все еще не сохранялись в моем сеансе.
build_shortcuts.sh
script = "$(cat $@ | sed -r -e 's/#[A-Za-z0-9 ]*$//' -e '/^\s+/s/^\s+//' -e '/^\s*$/d' -)"
# strip comments, entry level indentation & empty lines (in that order) from filestream
echo "${script}" | while read shortcut; do
cut=$(echo "${shortcut}" | awk '{ print $1 }')
dest=$(echo "${shortcut}" | awk '{ $1=nil; print $0 }')
dest = "${dest:1}" # trim leading whitespace character
alias "${cut}" &>/dev/null
if [ $? = 0 ]; then
echo "Warning: shortcut \"${cut}\" already exists" >&2
continue # by default, skip overwriting shortcuts
fi
echo alias ${cut} = "'cd ${dest}'"
alias "${cut}" = "'cd ${dest}'"
done
Я хочу, чтобы псевдонимы, установленные в цикле внутри скрипта, существовали вне скрипта. В настоящее время они не делают.
Я использую «GNU bash, версия 5.0.7 (1)-выпуск (x86_64-pc-linux-gnu)» на Arch Linux.
Из страница руководства Bash (раздел по Трубопроводы):
Each command in a pipeline is executed as a separate process (i.e., in a subshell)
Поскольку цикл выполняется как часть канала, это будет подоболочка, и команда псевдонима, которую вы выполняете в подоболочке, будет установлена только для этой подоболочки.
Возможный обходной путь — сохранить псевдонимы в списке, а затем выполнить фактические команды alias
во втором цикле, цикле, который не является частью канала или подоболочки.
Ваш сценарий можно немного сократить: ему не нужно обращаться к такому количеству внешних инструментов.
while read -r cut dest; do
if alias "${cut}" &>/dev/null; then
echo "Warning: shortcut \"${cut}\" already exists" >&2
else
echo alias ${cut} = "'cd ${dest}'"
alias "${cut}" = "'cd ${dest}'"
fi
done < <(
sed -E -e 's/#[A-Za-z0-9 ]*$//' -e '/^\s+/s/^\s+//' -e '/^\s*$/d' "$@"
)
после «сделано» я перенаправляю ввод из подстановки процесса: это позволяет избежать запуска цикла «во время чтения» в подоболочке.
Имейте в виду, что
~
не будет расширяться, если оно находится внутри кавычек.