bash while 循环中设置的别名不会持续存在
bash aliases set in while loop not persisting
好的,我写了一个 shell 脚本来读取格式为:
的文件
快捷方式 1 /path/to/directory1
捷径2 /path/to/directory2
它应该读取文件并构建别名,以便在映射目录中键入 shortcut1 cd 。问题是,循环中设置的任何别名都不会在脚本之外持续存在。
首先我只尝试 运行 脚本。
. ./build_shortcuts.sh "~/.shortcuts"
文件 ~/.shortcuts 包含的位置
dl ~/Downloads
music /music
dtop ~/Desktop
这没有用。然后我尝试在循环外设置一些别名。比如alias 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 }')
dest=$(echo "${shortcut}" | awk '{ =nil; print [=11=] }')
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, version 5.0.7(1)-release (x86_64-pc-linux-gnu)" 上 linux。
来自the Bash manual page(关于管道的部分):
Each command in a pipeline is executed as a separate process (i.e., in a subshell)
由于循环是作为管道的一部分完成的,因此它将是一个子 shell,并且您在子 shell 中执行的别名命令只会为该子 shell 设置。
一种可能的 work-around 是将别名保存到列表中,然后在第二个循环中执行实际的 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' "$@"
)
在 "done" 之后,我正在重定向来自进程替换的输入:这避免了子外壳中来自 运行 的 "while read" 循环。
好的,我写了一个 shell 脚本来读取格式为:
的文件快捷方式 1 /path/to/directory1
捷径2 /path/to/directory2
它应该读取文件并构建别名,以便在映射目录中键入 shortcut1 cd 。问题是,循环中设置的任何别名都不会在脚本之外持续存在。
首先我只尝试 运行 脚本。
. ./build_shortcuts.sh "~/.shortcuts"
文件 ~/.shortcuts 包含的位置
dl ~/Downloads
music /music
dtop ~/Desktop
这没有用。然后我尝试在循环外设置一些别名。比如alias 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 }')
dest=$(echo "${shortcut}" | awk '{ =nil; print [=11=] }')
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, version 5.0.7(1)-release (x86_64-pc-linux-gnu)" 上 linux。
来自the Bash manual page(关于管道的部分):
Each command in a pipeline is executed as a separate process (i.e., in a subshell)
由于循环是作为管道的一部分完成的,因此它将是一个子 shell,并且您在子 shell 中执行的别名命令只会为该子 shell 设置。
一种可能的 work-around 是将别名保存到列表中,然后在第二个循环中执行实际的 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' "$@"
)
在 "done" 之后,我正在重定向来自进程替换的输入:这避免了子外壳中来自 运行 的 "while read" 循环。