Проверка bash и csh, если команда встроена

Как я могу проверить bash и csh, если команды встроены? Есть ли метод, совместимый с большинством оболочек?

5 ответов


вы можете попробовать использовать which в csh или type в bash. Если что-то является встроенной командой, она так и скажет; в противном случае вы получите местоположение команды на своем пути.

в 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.


в bash, вы можете использовать с . Полную информацию можно найти в bash-builtins man-страница, но соответствующий бит:

тип -t имя

если -t используется опция, тип печатает строку, которая является одной из alias, keyword, function, builtin или file если имя-это псевдоним, зарезервированное слово оболочки, функция, встроенный или дисковый файл соответственно. Если имя не найдено, то ничего нет печатается, и возвращается состояние выхода false.

следовательно, вы можете использовать такие как:

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

на bash используйте type command


на csh, вы можете использовать:

which command-name

если он встроенный, он скажет так. Не уверен, что это работает так же для bash. Но мы осторожны с псевдонимами. Для этого могут быть варианты.


другие ответы здесь близки, но все они терпят неудачу, если есть псевдоним или функция с тем же именем, что и команда, которую вы проверяете.

вот мое решение:

на 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:  command"
    return 1
  fi
  cmd=
  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

откройте вложенную оболочку, чтобы удалить любые псевдонимы или имена команд с тем же именем. Затем в подрешетке используйте whence -v. В этом решении также есть дополнительный архаичный синтаксис для поддержки ksh88.

isbuiltin() {
  if [[ $# -ne 1 ]]; then
    echo "Usage:  command"
    return 1
  fi
  cmd=
  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
}

использование Решение

как только вы применили вышеупомянутое решение в оболочке по вашему выбору, вы можете использовать его следующим образом...

в командной строке:

$ 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