Answers:
在某些系统上,which -a
显示所有匹配项。如果您的shell是bash或zsh¹,则可以type
改用:type foo
显示第一个匹配项并type -a foo
显示所有匹配项。这三个命令type
,which
并whence
做几乎相同的事情; 在外壳程序和操作系统之间,它们在可用性,选项以及它们确切报告的内容方面有所不同。type
始终可用,并显示所有可能的类似命令的名称(别名,关键字,shell内置插件,函数和外部命令)。
显示所有匹配项的唯一完全可移植的方法是解析$PATH
自己。这是一个执行此操作的shell脚本。如果您将其设为shell函数,请确保将函数主体括在括号中(以使更改为IFS
且set -f
不要转义该函数),然后更改exit
为return
。
#!/bin/sh
set -f # disable globbing
IFS=: # break words at : only
not_found=1
for d in $PATH; do
if [ -f "$d/$x" ] && [ -x "$d/$x" ]; then
printf '%s\n' "$d/$x"
not_found=0
fi
done
exit $not_found
¹ 还是按照文档中的ksh 93,尽管ksh 93s + 2008-01-31仅在我尝试时才打印第一个匹配项。
sh
如果中有空组件,则该代码将无法正常工作$PATH
。还要注意,在中,冒号$IFS
是一个字段定界符(至少在POSIX shell中)$PATH
,用作字段分隔符。请参阅which
在Debian上找到的脚本以获取正确的实现。
type
中内置ksh93u+ 2012-08-01
似乎正常工作。
--all或-a标志将显示路径中的所有匹配项和别名(至少在Fedora,Ubuntu和CentOS上):
which -a which
在AIX和Solaris上,这将使您接近:
echo "$PATH" | sed -e 's/:/ /g' | \
while read -r p; do find "$p" -type f -name "which"; done
$PATH
包含空格或shell globbing字符,则脚本将无法工作。read -r
是应对反斜杠所必需的。这不是一个好方法,因为find
它将花费很长时间,并且如果目录中$PATH
包含子目录,则可能返回虚假匹配。幸运的是,find
这里没有用;看我的答案。
如果您没有which
支持服务-a
或没有支持whence
服务,请自己动手:
#!/bin/sh -f
IFS=":"
for PART in $PATH
do
if test -x "$PART/$1"
then
echo $PART/$1
fi
done
set -f
关闭未受保护的设备上的Globing功能$PATH
。test -f
还不够,因为这里只需要可执行文件;你需要test -x
。嗯,我意识到我忘记了脚本中的常规文件测试。
whence README.txt
可能性不大whence "file* wi?h we!rd name"
。只是试图说明遍历是多么容易$PATH
。
ksh和zsh具有“因此”作为内置的shell。 whence -a
在zsh下执行您想要的操作:
7:27AM 7 % whence -a cat
/usr/bin/cat
/bin/cat
/usr/bin/cat
/bin/cat
我必须清理zsh中的PATH,其中有很多重复项。whence -a
在ksh下的工作方式不同:
$ whence -a cat
cat is a tracked alias for /usr/bin/cat
我不得不说,这似乎也是一种潜在的有用行为。
which --all
。