-1

Я хочу, чтобы скрипт оболочки написал сообщение в зависимости от того, удастся или нет tar , но этот скрипт работает неправильно:

TAR=$(tar -cf Archiv.tar myfolder/ myotherfolder/)
if [ ! "$TAR" = "/dev/null" ]; then
   echo "success"
else
  echo "error - no such Directory or file"
fi

В чем проблема?

2 ответа2

4

Мне неизвестна ситуация, когда tar выдаст /dev/null чтобы сообщить об ошибке, именно так ваш код пытается обнаружить ошибку. Это правильный способ проверки на наличие ошибок:

if tar -cf Archiv.tar myfolder/ myotherfolder/
then
    echo "success"
else
    echo "error - no such Directory or file"
fi

Вам, вероятно, не нужен else случай, потому что сам tar будет жаловаться в этом случае. Если ваше использование /dev/null должно было подавить жалобы tar чтобы вы могли заменить свое собственное сообщение, тогда первая строка должна быть:

if tar -cf Archiv.tar myfolder/ myotherfolder/ > /dev/null 2>&1

Обратите внимание, что здесь мы не используем квадратные скобки. На самом деле это псевдоним для встроенной команды оболочки с именем test(1) которая выполняет логические операции и возвращает 0 или ненулевое значение, чтобы обозначить успех или неудачу соответственно. if в свою очередь, проверяет это 0/ ненулевое возвращение, поэтому для проверки успешности программы, такой как tar которая возвращает ненулевое значение при сбое, вам не нужно включать test или его псевдоним [ .

Если вы обучались языку программирования, который требует некоторой пунктуации вокруг выражения if так что отсутствие пунктуации беспокоит вас здесь, вы можете переписать первую строку следующим образом:

tar -cf Archiv.tar myfolder/ myotherfolder/
if [ $? = 0 ]

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

Это, возможно, понятнее, но немного расточительно.

0

Как обычно, есть более одного способа сделать то, что вы пытались.
Это (возможно, компактный) способ сделать это:

#!/bin/bash
TAR_COMMAND='tar -cf Archiv.tar myfolder/ myotherfolder/ 2>/dev/null'
MSG_OK='### Work well DONE ### '   # A more common way to use a variable
MSG_ERR='### OPS IT FAILS ###  '    

$TAR_COMMAND && echo $MSG_OK || echo $MSG_ERR

Короткие заметки

  • Если вам не нужно сохранять статус выхода (или код выхода) вашей команды, вы можете использовать ее сразу после операторов AND, && и OR, || [ 1 ].
    Логика: cmd1 && cmd2 , cmd2 будет выполняться, только если cmd1 без ошибок (с кодом выхода 0). Вместо этого с cmd1 || cmd3 , cmd3 будет выполняться только в том случае, если cmd1 завершится с ошибкой (код ошибки отличается от 0).

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

    mycommand               # you execute your command
    ExitCodeToUseLater=$?   # So I can use it later in the script
    # ... other stuffs ...
    [ $ExitCodeToUseLater = 0  ]  && echo "It was gone ok " 
    # ... again other stuffs ...
    [ $ExitCodeToUseLater = 0  ] || echo "# Never a time that it goes as I want"
    
  • В сценариях bash, а также в make-файлах [ 2a , 2b ] вы можете найти команду со многими опциями, записанными в переменную, чтобы сделать код более читабельным (как вы можете видеть выше для переменной TAR_COMMAND). Запись в оболочку переменной $MyVar будет такой же, как запись в оболочке того, что написано внутри [ 3 ]. Это работает в сценарии тоже. Возможно, вам придется обратить внимание на правила расширения и замены bash, о которых вы можете узнать больше из man bash .

  • /dev/null - это устройство Null [ 4 ] , «файл устройства, который отбрасывает все записанные в него данные, но сообщает, что операция записи прошла успешно» . Его можно использовать для подачи пустого ввода в команду (</dev/null) или для передачи в "абсолютном молчании" стандартного вывода или стандартной ошибки [ 5 ].

Всё ещё ищете ответ? Посмотрите другие вопросы с метками .