Проверка успешности команды в операторе bash `if [ .. ]`

Я пытаюсь автоматизировать резервное копирование наших приложений. Частью процесса является проверка статуса выхода egrep в if заявление:

if [ ! -f /opt/apps/SiteScope_backup/sitescope_configuration.zip ] ||
   [ egrep -i -q "error|warning|fatal|missing|critical" "$File" ]
then 
  echo "testing"
fi

Я ожидал, что это выведет testing потому что файл существует и egrep возвращает успех, но вместо этого я получаю ошибку:

-bash: [: too many arguments

Я пробовал со всеми видами синтаксиса - дополнительные скобки, кавычки и т. Д., Но ошибка все еще сохраняется.

Пожалуйста, помогите мне понять, где я иду не так.

2 ответа

Решение

Вы делаете общую ошибку, полагая, что [ является частью if синтаксис оператора Это не; синтаксис if это просто

if command; then
    ... things which should happen if command's result code was 0
else
    ... things which should happen otherwise
fi

Один из общих commandмы используем [ который является псевдонимом для команды test, Это простая команда для сравнения строк, чисел и файлов. Он принимает довольно узкую комбинацию аргументов и имеет тенденцию генерировать вводящие в заблуждение и вводящие в заблуждение сообщения об ошибках, если вы не передадите ему ожидаемые аргументы. (Или, скорее, сообщения об ошибках адекватны и полезны, как только вы к этому привыкнете, но их легко понять, если вы не используете их.)

Здесь вы хотите проверить результат команды egrep:

if [ ! -f /opt/apps/SiteScope_backup/sitescope_configuration.zip ] ||
   egrep -i -q "error|warning|fatal|missing|critical" "$File"
then
    echo "testing"
fi

В общем случае command может быть конвейером или списком команд; затем код выхода из последней команды - это статус, который if рассмотрим, аналогично тому, как последняя команда в сценарии определяет состояние выхода из сценария.

Эти составные команды могут быть сколь угодно сложными, как

if read thing
    case $thing in
      '' | 'quit') false;;
      *) true;;
    esac
then ...

но на практике вы редко видите более одной команды в if заявление (хотя это не неслыханно; ваше сложное заявление с || хороший пример!)

Исторические причины test в качестве общей кухонной раковины вещей авторы не хотели делать часть синтаксиса if является одним из менее привлекательных конструкций оригинальной оболочки Bourne. Баш и zsh предложить альтернативы, которые являются менее громоздкими (например, [[ двойные скобки в bash) и конечно же POSIX test гораздо более вспыльчивый, чем оригинальное творение Bell Labs.

Это работает: поместите ваш egrep в "$()", удалите -q и сравните строку:

if [ ! -f /opt/apps/SiteScope_backup/sitescope_configuration.zip ] ||
   [ "$(egrep -i 'error|warning|fatal|missing|critical' $File)" != "" ];
then

   echo "testing";

fi
Другие вопросы по тегам