1 #!/bin/bash
2 # inpath -- 验证指定程序是否有效,或者能否在PATH目录列表中找到。
3 in_path()
4 {
5 # 尝试在环境变量PATH中找到给定的命令。如果找到,返回0;
6 # 如果没有找到,则返回1。注意,该函数会临时修改IFS(内部字段分隔符),
7 # 不过在函数执行完毕时会将其恢复原状。
8 cmd=$1 ourpath=$2 result=1
9 oldIFS=$IFS IFS=":"
10
11 for directory in $ourpath
12 do
13 if [ -x $directory/$cmd ] ; then
14 result=0 # 如果执行到此处,那么表明我们已经找到了该命令。
15 fi
16 done
17 IFS=$oldIFS
18 return $result
19 }
20
21 checkForCmdInPath()
22 {
23 var=$1
24
25 if [ "$var" != "" ] ; then
26 if [ "${var:0:1}" = "/" ] ; then
27 if [ ! -x $var ] ; then
28 return 1
29 fi
30 elif ! in_path $var "$PATH" ; then
31 return 2
32 fi
33 fi
34 }
35 if [ $# -ne 1 ] ; then
36 echo "Usage: $0 command" >&2
37 exit 1
38 fi
39
40 checkForCmdInPath "$1"
41 case $? in
42 0) echo "$1 found in PATH" ;;
43 1) echo "$1 not found or not executable" ;;
44 2) echo "$1 not found in PATH" ;;
45 esac
46
47 exit 0
工作原理:
checkForCmdInPath能够正常工作的关键在于,区分只包含程序名的变量(例如echo)与包含程序完整路径和文件名的变量(例如/bin/echo)。它的做法是检查给定值的第一个字符是否为/。因此,我们需要把第一个字符与变量值的其余部分分离开。
注意,变量切分语法${var:0:1}是一种可以在字符串中指定子串的简写法,从偏移处开始,按照给定长度截取(如果没有提供长度,则返回余下的全部字符串)。例如,表达式${var:10}将会从第11个字符开始返回变量$var余下的值,而${var:10:5}则返回第11个到第15个字符。具体的含义可通过下面的代码来观察:
[root@localhost scripts]# var="something wicked this way comes..."
[root@localhost scripts]# echo ${var:10}
wicked this way comes...
[root@localhost scripts]# echo ${var:10:6}
wicked
[root@localhost scripts]#
在代码清单中,这个语法只是用来查看指定路径是否以斜线起始。只要确定传入脚本的路径包含起始斜线,就检查是否能在文件系统中找到该路径。如果路径开头是/,则假定给出的是绝对路径,然后使用bash操作符-x 检查其是否存在。否则,将该值交给函数inpath,看看能否在默认的环境变量PATH的各个目录中找到。
要想以独立程序的形式运行这个脚本,首先需要在脚本底部加上一小段代码。这段代码负责获取用户输入并将其传给相应的函数。
if [ $# -ne 1 ] ; then
echo "Usage: $0 command" >&2
exit 1
fi
checkForCmdInPath "$1"
case $? in
0 ) echo "$1 found in PATH" ;;
1 ) echo "$1 not found or not executable" ;;
2 ) echo "$1 not found in PATH" ;;
esac
exit 0
添加上面的代码之后,就可以直接调用脚本了,如接下来的“运行结果”所示。使用脚本完成工作之后,记得要把这段代码删除或注释掉,不然随后将其作为库函数使用时就乱套了。
运行结果:
在测试该脚本的时候,我们使用3个程序名来调用inpath:一个存在的程序、一个虽然存在但没有列入PATH中的程序,以及一个不存在但包含完整的合格文件名和路径的程序。测试结果:
[root@localhost scripts]# inpath echo
echo found in PATH
[root@localhost scripts]# inpath MrEcho
MrEcho not found in PATH
[root@localhost scripts]# inpath /usr/bin/MrEcho
/usr/bin/MrEcho not found or not executable
[root@localhost scripts]#
脚本中最后添加的那段代码将函数in_path的结果转换成了更易于阅读的文字,所以现在我们可以很容易地看到每种情况都按照预期得以处理。