在while循环中设置的bash别名不持久

时间:2019-05-27 13:59:25

标签: bash sh alias

好的,我编写了一个shell脚本来读取以下格式的文件:

快捷方式1 / path / to / directory1
快捷方式2 / path / to / directory2

及其应该读取的文件并建立别名,以便在映射的目录中键入快捷方式cd。问题是,循环中设置的任何别名都不会在脚本之外持续存在。

首先,我尝试仅运行脚本。

  

。 ./build_shortcuts.sh“〜/ .shortcuts”

〜/ .shortcuts文件所在的位置

  

dl〜/下载
  音乐/ music
  dtop〜/桌面

这没有用。然后,我尝试在循环外设置一些别名。例如别名hello ='world';别名world ='hellob'。我重新运行了该脚本,输入了别名以获取别名列表,它确实包含了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

我希望在脚本中的循环中设置的别名存在于脚本之外。目前他们还没有。

我正在arch Linux上的“ GNU bash,版本5.0.7(1)-发行版(x86_64-pc-linux-gnu)”上运行。

2 个答案:

答案 0 :(得分:2)

来自the Bash manual page(关于管道的部分):

  

管道中的每个命令都作为一个单独的进程(即在子shell中)执行

由于循环是作为管道的一部分完成的,因此它将是一个子外壳,并且您在子外壳中执行的alias命令将仅为此子外壳设置。

可能的解决方法是将别名保存到列表中,然后在第二个循环中执行实际的alias命令,该循环不属于管道或子shell。

答案 1 :(得分:0)

您的脚本可以减少一点:它不需要调用那么多外部工具。

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' "$@"
)

“完成”之后,我将从流程替换中重定向输入:这避免了“边读边”循环在子shell中运行。