Псевдонимы bash, установленные в цикле while, не сохраняются

Хорошо, я написал сценарий оболочки для чтения файла в формате:

ярлык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.

Имейте в виду, что ~ не будет расширяться, если оно находится внутри кавычек.

glenn jackman 27.05.2019 16:22
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
0
1
196
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Ответ принят как подходящий

Из страница руководства 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' "$@"
)

после «сделано» я перенаправляю ввод из подстановки процесса: это позволяет избежать запуска цикла «во время чтения» в подоболочке.

Другие вопросы по теме