我有一个名为“onewhich”的小脚本。它的目的是表现得像which
,除了它只会第一次出现指定为选项的任何可执行文件,按照它们在路径中出现的顺序找到。
例如,如果我的路径是/opt/bin:/usr/bin:/bin
,并且我同时拥有/opt/bin/runme
和/usr/bin/runme
,那么命令onewhich runme
将返回/opt/bin/runme
。
但是,如果我也有一个/usr/bin/doit
,那么该命令onewhich doit runme
将返回/usr/bin/doit
。
这个想法是遍历路径,检查指定的每个可执行文件,如果存在,则显示并退出。
这是到目前为止的脚本。
#!/bin/sh
for what in "$@"; do
for loc in `echo "${PATH}" | awk -vRS=: 1`; do
if [ -f "${loc}/${what}" ]; then
echo "${loc}/${what}"
exit 0
fi
done
done
exit 1
问题是,我想更好地处理带有特殊字符的 PATH 目录。StackOverflow 上的每一个 shell 问题都在谈论使用 awk 和 sed 等工具解析路径有多糟糕。甚至还有一个关于它的bash 常见问题解答条目。(附带条件:我没有为此使用 bash,但该建议仍然有效。)
所以我尝试重写脚本以分隔管道中的路径,就像这样“
#!/bin/sh
for what in "$@"; do
echo "${PATH}" | awk -vRS=: 1 | while read loc ; do
if [ -f "${loc}/${what}" ]; then
echo "${loc}/${what}"
exit 0
fi
done
done
exit 1
我不确定这是否给了我任何真正的优势(因为$loc
仍在引号内),但它也不起作用,因为由于某种原因,exit 0
似乎被忽略了。或者......它退出了某些东西(可能是带有终止管道的while循环的子shell),但脚本以1
每次的值退出。
有什么更好的方法来逐步浏览目录${PATH}
而不会有特殊字符混淆事物的风险?
或者,我是在重新发明轮子吗?是否有一种方法可以内置到现有的 shell 工具中?
这需要在 Linux 和 FreeBSD 中运行,这就是为什么我用 Bourne 而不是 bash 编写它的原因。
谢谢。