pev*_*vik 4 shell shell-builtin
#!/bin/sh
foo() {
echo "in foo"
}
type foo
Run Code Online (Sandbox Code Playgroud)
checkbashisms.pl
明明不喜欢type
,为什么?
$ checkbashisms.pl foo.sh
possible bashism in foo.sh line 7(type):
type foo
Run Code Online (Sandbox Code Playgroud)
不是POSIX吗?但是所有常见的外壳都支持它(即bash
, zsh
, dash
, busybox sh
, mksh
; 甚至在ksh
; 也许只是csh
不支持它),难道不应该有一种方法来抑制这个警告吗?
Ste*_*itt 11
type
是POSIX 的一部分,但作为 X/Open Systems Interfaces 选项 (XSI) 的一部分。该checkbashisms
手册页明确地说:
请注意,在此上下文中 bashism 的定义大致等同于“POSIX 不需要支持的 shell 功能”;这意味着在 POSIX 的可选部分下可能允许某些标记的问题,例如 XSI 或用户可移植性。
Sotype
被标记,因为它是一个可选功能。
checkbashisms
除了从脚本中删除它们之外,我不知道有什么方法可以禁用 中的特定警告。
考虑command -v foo
或command -V foo
代替type foo
。有人告诉我它更可靠,更可能是内置的。
让我们在$PATH
可执行文件、内置函数、函数和别名上进行测试:
#!/bin/sh
foo() {
echo "in foo"
}
bar=foo
for cmd in sed command foo bar; do
type "$cmd"
command -V "$cmd"
command -v "$cmd"
done
Run Code Online (Sandbox Code Playgroud)
输出(使用破折号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'
Run Code Online (Sandbox Code Playgroud)
(注意:sed
不是别名!也许这指的是 dash 的命令位置哈希表?)
尝试在 bash 中运行它,你会得到错误type
,command -V
因为 bash 没有在非交互式脚本中启用别名。Bash 还会显示整个函数定义?——在多行——?given 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 变量(如命令搜索和执行中所述)找到的任何实现定义的函数,都应进行标识,并在字符串中包含绝对路径名。
- 其他外壳函数应标识为函数。
- 别名应标识为别名及其定义包含在字符串中。
- 特殊内置实用程序应标识为特殊内置实用程序。
- 与 PATH 搜索无关的常规内置实用程序应标识为常规内置实用程序。(不需要使用“常规”一词。)
- 外壳保留字应标识为保留字。
在编写 shell 脚本时,我强烈建议使用command -v
而不是type
orcommand -V
因为它是三个中唯一具有定义输出的一个。再说一次,我的大多数脚本通过一个静默的辅助函数调用它,该函数在确定我们是否有命令时完全忽略其输出:
we_have() { command -v "$1" >/dev/null 2>&1; }
if we_have obscure-command; then
osbcure-command …
fi
Run Code Online (Sandbox Code Playgroud)