使用从文本文件中提取的目录列表扩展 PATH,波浪字符 (~) 未扩展为 HOME

Expanding the PATH with a list of directories extracted from a text file, the tilda (~) character not expanded to HOME

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!
$

然而, 问题中简要讨论了一些不良影响,包括以下症状:

$ bl 1
$ sh -c 'bl 1'
sh: bl: command not found
$
$ bl 1
$ whereis bl
bl:
$

一致认为,在 PATH 扩展之前,'~' 字符应该扩展到用户的 HOME。如何实现,同时还保留外部文件作为 PATH 扩展的目录源?当前方法的问题在哪里?帮助非常感谢:)

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.

波浪号扩展(或任何其他 shell 扩展)在解释 PATH 变量时不会发生。 PATH 的解释方式在 POSIX environment variables 8.3 中指定。它有自己的规则,与 shell 扩展无关,与波浪线扩展无关。

How can it be achieved

您必须创建自己的 shell,它不符合 posix 并且在 command search and execution 期间搜索 PATH 变量时进行波浪线扩展。这样的 shell 将是不合格的。最简单的方法是采用 bash 并对其进行修补。

更现实的方法是将文件内容中的 ~ 替换为 $HOME 内容,或者在读取流时使用简单的 sed 替换。

Where lays the issue with the current approach?

这个问题很可能是由于误解了 shell 的运作方式 - 展开工作的地方。