好的,我编写了一个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)”上运行。
答案 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中运行。