用从文本文件中提取的目录列表扩展PATH,'〜'字符未扩展为HOME

时间:2019-11-18 15:36:30

标签: bash path sh archlinux

通过从文本文件中提取的目录列表来扩展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扩展的目录源?当前方法的问题在哪里?帮助非常感谢:)

1 个答案:

答案 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的操作方式-扩展在哪里工作。