通过从文本文件中提取的目录列表来扩展PATH;
$ cat ~/.path
~/.local/bin
~/W-space/esp/esp-open-sdk/xtensa-lx106-elf/bin
~/W-space/research/recognition/voxforge/bin
~/W-space/research/recognition/voxforge/bin/julius-4.3.1/bin
像这样(可以在BASH的启动文件之一中找到以下内容):
declare -a BATH_ARRAY=($(cat ~/.path)) 2>/dev/null # extend path
for BATH in "${BATH_ARRAY[@]}"
do
case ":${PATH}:" in
*:${BATH}:*) ;;
*) PATH=${PATH}:$BATH && export PATH;;
esac
done
从~/.path
文件提取的PATH扩展条目数组的基本迭代。结果PATH包含'〜'字符(因此是错误的问题):
$ echo $PATH
/usr/local/sbin:/usr/local/bin:~/.local/bin
在~/.local/bin
内部,有一个我可以调用的bl
脚本,如下所示:
$ ls -l ~/.local/bin/bl
-rwxr-xr-x 1 romeo romeo 6304 Nov 17 09:06 /home/romeo/.local/bin/bl*
$ bl 1 #no error!
$
然而,'sh' environment does not respect the PATH extensions, user's local PATH not in effect?问题中简要讨论了一些不良影响,其中包括如下症状:
$ bl 1
$ sh -c 'bl 1'
sh: bl: command not found
$
$ bl 1
$ whereis bl
bl:
$
一致认为,在扩展PATH之前,应将'〜'字符扩展到用户的HOME。如何实现它,同时又将外部文件保留为PATH扩展的目录源?当前方法的问题在哪里?帮助非常感谢:)
答案 0 :(得分:2)
TL; DR只需自己替换~
,就像这样:
while IFS=$'\n' read -r BATH; do
# also ex. readlink -m could be added to shorten the path
case ":${PATH}:" in
*:${BATH}:*) ;;
*) PATH=${PATH}:$BATH ;;
esac
done < <(sed 's~^\~~'"$HOME"'~' .path)
export PATH
~
在tilde expansion期间展开。然后将波浪号~
替换为用户变量HOME
的内容。
例如,当shell解释一行时,发生shell扩展。因此,当用户键入echo ~
时,它会很好地打印echo /home/kamil
。
解释PATH
变量时不会发生波浪号扩展(或任何其他shell扩展)。 POSIX environment variables 8.3中指定了PATH
的解释方式。它具有自己的规则,与Shell扩展无关,与tilde扩展无关。
如何实现
在command search and execution期间搜索PATH变量时,您必须创建自己的不符合posix并进行波浪线扩展的shell。这样的壳将是不合格的。最简单的方法是进行bash修补。
一种更现实的方法是将文件内容中的~
替换为$HOME
内容,或者在读取流时进行简单的sed
替换。
当前方法的问题出在哪里?
问题很可能是由于误解了shell的操作方式-扩展在哪里工作。