Checking in bash and csh if a command is builtin
Asked Answered
B

5

22

How can I check in bash and csh if commands are builtin? Is there a method compatible with most shells?

Bioecology answered 13/9, 2011 at 9:37 Comment(2)
This should really be two questions. bash being compliant with POSIX sh, and csh being entirely uncompliant, the shells are entirely different; you might as well ask a question about how to do a thing in Python and Java.Outflow
As someone who pretty much exclusively uses bash and csh on a daily basis, and who found this in their first google search result, I found the scope of the question helpful.Rillings
L
22

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.

Landis answered 13/9, 2011 at 9:42 Comment(1)
type also seems to work with fish shell.Mind
L
13

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
Landri answered 13/9, 2011 at 9:43 Comment(0)
S
4

For bash, use type command

Strontia answered 13/9, 2011 at 9:42 Comment(0)
U
2

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.

Upstart answered 13/9, 2011 at 9:41 Comment(0)
B
1

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
Biotype answered 11/5, 2015 at 14:13 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.