Bash Shell指定位置查找文件,你需要执行、读入(source)或读取某个文件,但该文件位于 $PATH
之外的其他位置。
source 本身是 bash shell 的内建命令,能够在当前 shell 的上下文中读取并执行指定文件中的命令。source 一词有时候也作为动词使用,目前尚无较好的统一译法,本文中选择将其译为“读入”。
解决方案
如果打算读入的某个文件位于 $PATH
所列路径之中,直接读入就行了。如果设置了 shell 选项 sourcepath(默认启用),bash 的内建命令 source(该命令还有另一个 POSIX 名称 .,虽然够简短且易于输入,但确实容易漏看)会搜索 $PATH
。
source myfile
如果想要仅在某个文件位于 $PATH
所列路径之中且可执行时才执行该文件,同时 bash 版本为 2.05b 或更高,可以用 type -P 来搜索 $PATH
。和 which 命令不同,type -P 只会在找到文件时才产生输出,这使其更易于在下列情况中使用:
LS=$(type -P ls)
[ -x "$LS" ] && $LS
# --或者--
LS=$(type -P ls)
if [ -x "$LS" ]; then
: commands involving $LS here
fi
如果需要查找可能包括 $PATH
在内的多个位置,可以使用 for 循环。要想搜索 $PATH
中的各个部分,使用变量替换运算符 ${variable//pattern/replacement}
将所有的 :
分隔符替换成空格,使之成为一个个独立的单词,然后用 for 迭代单词列表。具体做法如下所示。
for path in ${PATH//:/ }; do
[ -x "$path/ls" ] && $path/ls
done
# --或者--
for path in ${PATH//:/ } /opt/foo/bin /opt/bar/bin; do
[ -x "$path/ls" ] && $path/ls
done
如果文件未在 $PATH
所列出的路径中,而是在其他位置,甚至连名字都可能不一样,那么可以在 for 语句中列出所有的完整路径。
for file in /usr/local/bin/inputrc /etc/inputrc ~/.inputrc; do
[ -f "$file" ] && bind -f "$file" && break # 使用找到的第一个文件
done
根据需要执行其他测试。例如,你可能想在登录时使用 screen(如果系统中有该命令)。
for path in ${PATH//:/ }; do
if [ -x "$path/screen" ]; then
# 如果screen(1)存在且可执行:
for file in /opt/bin/settings/run_screen ~/settings/run_screen; do
[ -x "$file" ] && $file && break # 执行找到的第一个可执行文件
done
fi
done
讨论
用 for 语句迭代所有的可能位置看起来有些杀鸡用牛刀了,但其实这种用法非常灵活,允许你搜索所需要的任何位置、进行任何测试,并对找到的文件执行任何操作。通过将 $PATH
中的每个 :
替换成空格,可以形成for 语句所要求的以空白字符作为分隔的单词列表(任何以空白字符分隔的列表都管用)。根据需要灵活运用该技术,能够帮你编写出一些对文件位置适应性颇高的 shell 脚本,不仅非常灵活,而且具备可移植性。
也许你想通过设置 $IFS=':'
来直接解析 $PATH
,而不是将其拆解到 $path
中。这样做当然可以,但涉及一些额外工作,而且也不够灵活。
你可能也想要像下面这样做:
[ -n "$(which myfile)" ] && bind -f $(which myfile)
这里的问题不在于文件存在时,而在于文件不存在时。which 命令在不同系统上行为各异。Red Hat 的 which 命令其实是一个别名,设置了各种命令行选项,如果其参数也是别名,则可以提供与该参数相关的细节信息;指定的参数不存在时,则返回消息,表明未查找到(Debian 或 FreeBSD 上的 which 不会这么做)。要是在 NetBSD 上尝试上面这行,你会得到 no myfile in /sbin /usr/sbin /bin /usr/bin /usr/pkg/sbin /usr/pkg/bin /usr/X11R6/ bin /usr/ local/sbin /usr/local/bin
,这不会是你想看到的。
这种情况下,command 命令也值得留意。该命令出现的时间早于 type -P,有时也许能派上用场。
Red Hat Enterprise Linux 4.x 的行为与以下类似。
$ alias which
alias which='alias | /usr/bin/which --tty-only --read-alias --show-dot --show-tilde'
$ which rd
alias rd='rmdir'
/bin/rmdir
$ which ls
alias ls='ls --color=auto -F -h'
/bin/ls
$ which cat
/bin/cat
$ which cattt
/usr/bin/which: no cattt in (/usr/kerberos/bin:/usr/local/bin:/bin:/usr/bin:/usr/
X11R6/bin:/home/jp/bin)
$ command -v rd
alias rd='rmdir'
$ command -v ls
alias ls='ls --color=auto -F -h'
$ command -v cat
/bin/cat
Debian 和 FreeBSD(但不包括 NetBSD 或 OpenBSD)的行为与以下类似。
$ alias which
-bash3: alias: which: not found
$ which rd
$ which ls
/bin/ls
$ which cat
/bin/cat
$ which cattt
$ command -v rd
-bash: command: rd: not found
$ command -v ls
/bin/ls
$ command -v cat
/bin/cat
$ command -v ll
alias ll='ls -l'
酷客网相关文章:
评论前必须登录!
注册