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而不是typeorcommand -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)