Подтвердить что ты не робот

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

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

4b9b3361

Ответ 1

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

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

Ответ 2

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

тип -t name

Если используется опция -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

Ответ 3

Для bash используйте type command

Ответ 4

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

which command-name

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

Ответ 5

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

Здесь мое решение:

В 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

Откройте под-оболочку, чтобы удалить любые псевдонимы или имена команд с тем же именем. Затем в подоболочке используйте 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 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.

Или вы можете использовать его как в script:

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