我还没有人提到这一点,我感到有些惊讶,但是您可以使用它readlink -f
来将相对路径转换为绝对路径,并将其原样添加到PATH中。
例如,要改善Guillaume Perrault-Archambault的答案,
pathappend() {
for ARG in "$@"
do
if [ -d "$ARG" ] && [[ ":$PATH:" != *":$ARG:"* ]]; then
PATH="${PATH:+"$PATH:"}$ARG"
fi
done
}
变成
pathappend() {
for ARG in "$@"
do
if [ -d "$ARG" ] && [[ ":$PATH:" != *":$ARG:"* ]]
then
if ARGA=$(readlink -f "$ARG") #notice me
then
if [ -d "$ARGA" ] && [[ ":$PATH:" != *":$ARGA:"* ]]
then
PATH="${PATH:+"$PATH:"}$ARGA"
fi
else
PATH="${PATH:+"$PATH:"}$ARG"
fi
fi
done
}
1.基础知识-这有什么用?
该readlink -f
命令(除其他事项外)会将相对路径转换为绝对路径。这使您可以做类似的事情
$ cd / path / to / my / bin / dir
$ pathappend 。
$ echo“ $ PATH”
<您的旧路径>:/ path / to / my / bin / dir
2.为什么我们要两次测试是否在PATH中?
好吧,考虑上面的例子。如果用户第二次
从目录中说出,
将为。当然,不会出现在中。但随后将被设置为
(已等于的绝对路径),该值已在中。因此,我们需要避免加入到第二次。pathappend .
/path/to/my/bin/dir
ARG
.
.
PATH
ARGA
/path/to/my/bin/dir
.
PATH
/path/to/my/bin/dir
PATH
也许更重要的readlink
是,顾名思义,它的主要目的是查看符号链接并读出其包含(即指向)的路径名。例如:
$ ls -ld /usr/lib/perl/5.14
-rwxrwxrwx 1 root root Sep 3 2015 /usr/lib/perl/5.14 -> 5.14.2
$ readlink /usr/lib/perl/5.14
5.14.2
$ readlink -f /usr/lib/perl/5.14
/usr/lib/perl/5.14.2
现在,如果您说pathappend /usr/lib/perl/5.14
,并且您已经/usr/lib/perl/5.14
在PATH中,那就好了;我们可以保持原样。但是,如果/usr/lib/perl/5.14
您的PATH中还没有包含该代码,则我们调用readlink
并获取ARGA
= /usr/lib/perl/5.14.2
,然后将其添加到中PATH
。但是请稍等一下-如果您已经说过pathappend /usr/lib/perl/5.14
,那么您已经/usr/lib/perl/5.14.2
在PATH中了,再次,我们需要检查一下以避免将其添加到PATH
第二次。
3.处理什么if ARGA=$(readlink -f "$ARG")
?
如果不清楚,此行测试是否readlink
成功。这只是好的防御性编程实践。如果我们要使用命令m的输出
作为命令 n的一部分(其中m < n),则最好检查命令m是否 失败并以某种方式处理。我不认为它会失败-但是,正如如何从OS X
和其他地方检索任意文件的绝对路径中所讨论的那样,它是GNU发明。在POSIX中未指定它,因此它在Mac OS,Solaris和其他非Linux Unix中的可用性值得怀疑。(实际上,我刚读了一条评论,内容为“readlink
readlink
readlink -f
在Mac OS X 10.11.6上似乎无法正常运行,但realpath
可以立即使用。”因此,如果您使用的系统没有readlink
,或者在readlink -f
无法正常工作的地方,则可以对其进行修改。使用脚本realpath
。)通过安装安全网,我们使代码更易于移植。
当然,如果您使用的系统没有readlink
(或 realpath
),那么您就不会想要这样做。pathappend .
第二个-d
测试([ -d "$ARGA" ]
)实际上可能是不必要的。我想不出$ARG
目录可以readlink
成功但$ARGA
目录不是成功 的任何情况。我只是复制并粘贴了第一个if
语句以创建第三个语句,然后-d
出于懒惰而将 测试留在那里。
4.还有其他意见吗?
是的 像这里的许多其他答案一样,该函数测试每个参数是否为目录,如果是,则对其进行处理,如果不是,则将其忽略。如果pathappend
仅在“ .
”文件(如.bash_profile
和.bashrc
)和其他脚本中使用,这可能(或可能不足够)。但是,如上面答案所示,以交互方式使用它是完全可行的。如果你这样做,你会很困惑
$ pathappend /usr/local/nysql/bin
$ mysql
-bash: mysql: command not found
您是否注意到我nysql
在pathappend
命令中说的而不是mysql
?那pathappend
什么也没说。它只是默默地忽略了错误的论点?
就像我在上面说的那样,处理错误是个好习惯。这是一个例子:
pathappend() {
for ARG in "$@"
do
if [ -d "$ARG" ]
then
if [[ ":$PATH:" != *":$ARG:"* ]]
then
if ARGA=$(readlink -f "$ARG") #notice me
then
if [[ ":$PATH:" != *":$ARGA:"* ]]
then
PATH="${PATH:+"$PATH:"}$ARGA"
fi
else
PATH="${PATH:+"$PATH:"}$ARG"
fi
fi
else
printf "Error: %s is not a directory.\n" "$ARG" >&2
fi
done
}