开发者

Checking in bash and csh if a command is builtin

How can I check in bash and csh if commands are builtin? Is there a method compatible with most shells?开发者_运维知识库


You can try using which in csh or type in bash. If something is a built-in command, it will say so; otherwise, you get the location of the command in your PATH.

In csh:

# which echo
echo: shell built-in command.

# which parted
/sbin/parted

In bash:

# type echo
echo is a shell builtin

# type parted
parted is /sbin/parted

type might also show something like this:

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

...which means that it's not a built-in, but that bash has stored its location in a hashtable to speed up access to it; (a little bit) more in this post on Unix & Linux.


In bash, you can use the type command with the -t option. Full details can be found in the bash-builtins man page but the relevant bit is:

type -t name

If the -t option is used, type prints a string which is one of alias, keyword, function, builtin, or file if name is an alias, shell reserved word, function, builtin, or disk file, respectively. If the name is not found, then nothing is printed, and an exit status of false is returned.

Hence you can use a check such as:

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

which would result in the output:

read
cd


For bash, use type command


For csh, you can use:

which command-name

If it's built-in, it will tell so. Not sure if it works the same for bash. We careful with aliases, though. There may be options for that.


The other answers here are close, but they all fail if there is an alias or function with the same name as the command you're checking.

Here's my solution:

In tcsh

Use the where command, which gives all occurrences of the command name, including whether it's a built-in. Then grep to see if one of the lines says that it's a built-in.

alias isbuiltin 'test \!:1 != "builtin" && where \!:1 | egrep "built-?in" > /dev/null || echo \!:1" is not a built-in"'

In bash/zsh

Use type -a, which gives all occurrences of the command name, including whether it's a built-in. Then grep to see if one of the lines says that it's a built-in.

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
}

In ksh88/ksh93

Open a sub-shell so that you can remove any aliases or command names of the same name. Then in the subshell, use whence -v. There's also some extra archaic syntax in this solution to support 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
}

Using the Solution

Once you applied the aforementioned solution in the shell of your choice, you can use it like this...

At the command line:

$ isbuiltin command

If the command is a built-in, it prints nothing; otherwise, it prints a message to stderr.

Or you can use it like this in a script:

if isbuiltin $cmd 2> /dev/null
then
  echo "$cmd is a built-in"
else
  echo "$cmd is NOT a built-in"
fi
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜