问题
The PATH is expanded by a list of directories extracted from a text file;
$ 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
like so (The following can be found in one of the BASH's startup files):
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
Basic iteration over the array of PATH expansion entries extracted from the ~/.path
file. The resultant PATH includes the '~' character (which is wrong hence the question):
$ echo $PATH
/usr/local/sbin:/usr/local/bin:~/.local/bin
Inside of the ~/.local/bin
there exists a bl
script I am able to invoke, like so:
$ 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!
$
However some undesired effects were briefly discussed in the 'sh' environment does not respect the PATH extensions, user's local PATH not in effect? question and include symptoms such as the following:
$ bl 1
$ sh -c 'bl 1'
sh: bl: command not found
$
$ bl 1
$ whereis bl
bl:
$
The consensus was that the '~' character should be expanded to the user's HOME before the PATH expansion. How can it be achieved, while also keeping an external file as a source of directories for the PATH expansion? Where lays the issue with the current approach? Help much appreciated :)
回答1:
TL;DR Just replace ~
yourself, something like:
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
The ~
is expanded during tilde expansion. The tilde ~
is then replaced by the content of the user variable HOME
.
The shell expansions happen for example when shell interprets a line. So when a user types echo ~
it nicely prints echo /home/kamil
.
Tilde expansion (or any other shell expansion) doesn't happen when interpreting the PATH
variable. How PATH
is interpreted is specified in POSIX environment variables 8.3. It has it's own rules, that are unrelated to shell expansions and unrelated to tilde expansion.
How can it be achieved
You have to create your own shell that doesn't conform to posix and does tilde expansion when searching the PATH variable during command search and execution. Such shell would be nonconforming. The easiest approach would be to take bash and patch it.
A more realistic approach is just to replace the ~
in the content of your file by $HOME
content or while reading the stream with simple sed
replacement.
Where lays the issue with the current approach?
The issue most probably comes from misinterpreting the way shell operates - where the expansions work.
来源:https://stackoverflow.com/questions/58918101/expanding-the-path-with-a-list-of-directories-extracted-from-a-text-file-the