#!/bin/sh
foo() {
echo "in foo"
}
type foo
checkbashisms.pl
明明不喜欢type
,为什么呢?
$ checkbashisms.pl foo.sh
possible bashism in foo.sh line 7(type):
type foo
不是POSIX吗?但所有常见的 shell 都支持它(即bash
, zsh
, dash
, busybox sh
, mksh
; 甚至在ksh
; 中也许只是csh
不支持它),难道没有办法抑制这个警告吗?
答案1
type
是POSIX 的一部分,但作为 X/开放系统接口选项 (XSI) 的一部分。手册checkbashisms
页明确地说
请注意,在此上下文中 bashism 的定义大致相当于“不需要 POSIX 支持的 shell 功能”;这意味着 POSIX 的可选部分(例如 XSI 或用户可移植性)可能允许标记的某些问题。
之所以type
被标记,是因为它是一个可选功能。
checkbashisms
除了从脚本中删除它们之外,我不知道有任何方法可以禁用 中的特定警告。
答案2
考虑command -v foo
或command -V foo
代替type foo
。有人告诉我它更可靠并且更有可能是内置的。
让我们在$PATH
可执行文件、内置函数、函数和别名上测试一下:
#!/bin/sh
foo() {
echo "in foo"
}
alias bar=foo
for cmd in sed command foo bar; do
type "$cmd"
command -V "$cmd"
command -v "$cmd"
done
输出(使用短跑0.5.11):
sed is /usr/bin/sed
sed is a tracked alias for /usr/bin/sed
/usr/bin/sed
command is a shell builtin
command is a shell builtin
command
foo is a shell function
foo is a shell function
foo
bar is an alias for foo
bar is an alias for foo
alias bar='foo'
(笔记:sed
不是别名!也许这指的是破折号散列命令位置表?)
尝试在 bash 中运行它,您会收到错误type
,command -V
因为 bash 不会在非交互式脚本中启用别名。 Bash 还将在给定的多行上显示整个函数定义command -V
,这确实很难解析。
POSIX定义command
的选项作为:
-p
使用 PATH 的默认值执行命令搜索,保证找到所有标准实用程序。
-v
将字符串写入标准输出,指示当前 shell 执行环境中 shell 将使用的路径名或命令(请参阅Shell执行环境),调用 command_name,但不调用 command_name。
- 实用程序、常规内置实用程序、包含字符的 command_names 以及使用 PATH 变量找到的任何实现定义的函数(如命令搜索和执行),应写为绝对路径名。
- shell 函数、特殊内置实用程序、与 PATH 搜索无关的常规内置实用程序以及 shell 保留字应仅写为它们的名称。
- 别名应写为代表其别名定义的命令行。
- 否则,不应写入任何输出,并且退出状态应反映未找到该名称。
-V
将一个字符串写入标准输出,指示 shell 在当前 shell 执行环境中如何解释 command_name 操作数中给定的名称(请参阅Shell执行环境),但不调用 command_name。尽管该字符串的格式未指定,但它应指示 command_name 属于以下哪一类别,并应包含所述信息:
- 实用程序、常规内置实用程序以及使用 PATH 变量找到的任何实现定义的函数(如命令搜索和执行),应如此标识并在字符串中包含绝对路径名。
- 其他 shell 函数应标识为函数。
- 别名应被标识为别名,并且它们的定义包含在字符串中。
- 特殊内置实用程序应标识为特殊内置实用程序。
- 与 PATH 搜索无关的常规内置实用程序应被标识为常规内置实用程序。 (不需要使用术语“常规”。)
- Shell 保留字应标识为保留字。
在编写 shell 脚本时,我强烈建议使用command -v
而不是type
or,command -V
因为它是三个中唯一具有定义输出的之一。话又说回来,我的大多数脚本都是通过一个静默的辅助函数来调用它的,该函数在确定我们是否有命令时完全忽略它的输出:
we_have() { command -v "$1" >/dev/null 2>&1; }
if we_have obscure-command; then
osbcure-command …
fi
答案3
该命令type
绝对不是 a bashism
,因为它是自 1984 年以来的一部分UNIX
。
然而,如果您使用的是仅提供基本兼容性的小型嵌入式平台,则该type
命令可能不存在。POSIX
如果您所在的平台自称为UNIX
-platform,则该type
命令是强制性的,因为UNIX
需要 -platform 来支持全部XSI
标准中提到的所谓增强功能POSIX
。
如果您正在寻找即使小型嵌入式系统也需要支持的半相似命令,您可能会喜欢使用:
command -V foo
反而。请注意,大写的 -V 选项command
打印与 类似但不一定相同的输出type
。
另请注意:标准未定义fromcommand -V
或 from 的输出格式。type
POSIX