在bash和csh中检查命令是否为内置命令

21

如何在Bash和Csh中检查命令是否内置?是否有一种适用于大多数Shell的方法?


1
这实际上应该是两个问题。bash 符合 POSIX sh 标准,而 csh 完全不符合标准,因此这两个 shell 是完全不同的;你可以问关于如何在 Python 和 Java 中完成某件事情的问题了。 - Charles Duffy
作为一个几乎每天都使用bash和csh的人,我在第一次谷歌搜索结果中找到了这个问题的范围非常有帮助。 - BryKKan
5个回答

21
你可以尝试在csh中使用which,或者在bash中使用type。如果某个命令是内置的,它会说明这一点;否则,你将得到命令在路径中的位置。
在csh中:
# which echo
echo: shell built-in command.

# which parted
/sbin/parted

在bash中:

# type echo
echo is a shell builtin

# type parted
parted is /sbin/parted

type 可能也显示类似于以下内容:

# type clear
clear is hashed (/usr/bin/clear)

这意味着它不是内置命令,但是bash将其位置存储在哈希表中以加速访问;Unix&Linux的这篇文章中有更详细的解释。


type 命令似乎也可以在 fish shell 中使用。 - Smar

13
在bash中,您可以使用带有-t选项的type命令。完整细节可以在bash-builtins手册页中找到,但相关部分如下:

type -t 名称

如果使用了-t选项,type会打印一个字符串,其中之一是aliaskeywordfunctionbuiltinfile,如果名称是别名、shell保留字、函数、内置或磁盘文件,则分别为。如果找不到名称,则不会打印任何内容,并返回错误退出状态。

因此,您可以使用以下检查:
if [[ "$(type -t read)" == "builtin" ]] ; then echo read ; fi
if [[ "$(type -t cd)"   == "builtin" ]] ; then echo cd   ; fi
if [[ "$(type -t ls)"   == "builtin" ]] ; then echo ls   ; fi

这将导致输出结果:
read
cd

4

对于 bash,请使用 type 命令


2
< p >对于csh,您可以使用:

which command-name

如果它是内置的,它会告诉您。 不确定它是否适用于bash。 但要注意别名。可能有相关选项。


1
这里的其他答案都很接近,但如果存在与您正在检查的命令同名的别名或函数,则它们都会失败。
以下是我的解决方案:
在tcsh中,使用where命令,该命令提供命令名称的所有出现情况,包括是否为内置。然后使用grep查看其中一行是否表示它是一个内置命令。
alias isbuiltin 'test \!:1 != "builtin" && where \!:1 | egrep "built-?in" > /dev/null || echo \!:1" is not a built-in"'

bash/zsh

使用 type -a 命令,它会返回所有命令的位置,包括是否为内建命令。然后使用 grep 命令查看其中是否有一行显示该命令是内建命令。

isbuiltin() {
  if [[ $# -ne 1 ]]; then
    echo "Usage: $0 command"
    return 1
  fi
  cmd=$1
  if ! type -a $cmd 2> /dev/null | egrep '\<built-?in\>' > /dev/null
  then
    printf "$cmd is not a built-in\n" >&2
    return 1
  fi
  return 0
}

ksh88/ksh93

打开一个子shell以便您可以删除任何同名的别名或命令名称。然后在子shell中使用whence -v。此解决方案还包括一些额外的古老语法以支持ksh88

isbuiltin() {
  if [[ $# -ne 1 ]]; then
    echo "Usage: $0 command"
    return 1
  fi
  cmd=$1
  if (
       #Open a subshell so that aliases and functions can be safely removed,
       #  allowing `whence -v` to see the built-in command if there is one.
       unalias "$cmd";
       if [[ "$cmd" != '.' ]] && typeset -f | egrep "^(function *$cmd|$cmd\(\))" > /dev/null 2>&1
       then
         #Remove the function iff it exists.
         #Since `unset` is a special built-in, the subshell dies if it fails
         unset -f "$cmd";
       fi
       PATH='/no';
       #NOTE: we can't use `whence -a` because it's not supported in older versions of ksh
       whence -v "$cmd" 2>&1
     ) 2> /dev/null | grep -v 'not found' | grep 'builtin' > /dev/null 2>&1
  then
    #No-op
    :
  else
    printf "$cmd is not a built-in\n" >&2
    return 1
  fi
}

使用该解决方案

一旦您在所选的shell中应用了上述解决方案,您可以像这样使用它...

在命令行中:

$ isbuiltin command

如果命令是内置的,它不会打印任何内容;否则,它会将一条消息打印到stderr。
或者你可以在脚本中这样使用它:
if isbuiltin $cmd 2> /dev/null
then
  echo "$cmd is a built-in"
else
  echo "$cmd is NOT a built-in"
fi

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接