Какой из них лучше: использование; или && для выполнения нескольких команд в одной строке?


428

В учебниках и практических занятиях я часто вижу комбинированные команды. Например,

sudo apt-get update && sudo apt-get install pyrenamer

Там , кажется, четыре возможных разъемов: &, &&, ||и ;. Хотя & разъем для меня понятен (он отправляет процесс в фоновый режим и оставляет терминал доступным), не ясно, в чем разница между &&и ;. И я не знал, ||пока Кая комментарий.

Следующие вопросы касаются разницы между двумя разъемами, но в основном это делается в комментариях:

Итак, вот несколько связанных вопросов:

  1. В чем разница между ;и &&?
  2. Когда вы должны использовать их соответственно? Было бы неплохо увидеть некоторые варианты использования: если я хочу выполнить команду, а затем после ее выключения мой компьютер, какой разъем выбрать?
  3. Каковы их преимущества и опасности ? Роби Басак упоминает в комментарии к этому ответу, что подобная команда cd /somewhere_else; rm -Rf *может иметь разрушительные последствия, например, в случае сбоя первого элемента в цепочке команд.
  4. Если уместно, откуда они берутся?

7
Есть еще один соединитель, с которым вы, возможно, не сталкивались: ||он такой же, как и &&тот, за исключением того, что он выполняет вторую команду только в том случае, если первая вышла с ненулевым (неудачным) состоянием.
Кая

4
Также обратите внимание, что запуск вашего скрипта с set -eостановит скрипт при сбое, как если бы все команды были связаны &&.
Чороба


3
Никто не ответил на вопрос 4 ... Я подозреваю, что поведение && и || был вдохновлен языком программирования C. В случае (x && y), если x оценивается как false, все выражение должно быть ложным, чтобы компилятор мог оптимизировать оценку y, если это было дорого. Современные стандарты C и C ++ действительно требуют такой оптимизации, поэтому программы могут смело предполагать, что y не будет оцениваться, если x равно false. Например, (ptr && ptr-> days> 31) не произойдет сбой, даже если ptr будет нулевым. Также в C операторы заканчиваются; независимо от того, есть ли другое утверждение в той же строке или нет.
Кевин

Ответы:


773

Cheatsheet:

A; B    # Run A and then B, regardless of success of A
A && B  # Run B if and only if A succeeded
A || B  # Run B if and only if A failed
A &     # Run A in background.

19
И, конечно A & B &,: запустите A в фоновом режиме, затем запустите B в фоновом режиме (независимо от успеха) и верните управление оболочке. Это часто работает примерно так же, как и запуск обоих процессов одновременно.
Ограниченное искупление

4
можно ли сказать: запустить a в фоновом режиме, а затем b в фоновом режиме, только если работал? (Я думаю & &&&?)
user230910

15
@ user230910: это было бы (A && B) &.
оставил около

5
Можете ли вы ссылаться на авторитетный документ для этого?
Хайме Хаблутцель

@Jack Когда выполняется из Cronjob, он не совсем следует этому правилу, понимаете почему? Для файла с питоном
CodeGuru

77

&&запускает вторую команду только в том случае, если первая вышла со статусом 0 (была успешной). ;запускает обе команды, даже если первая выходит с ненулевым статусом.

Ваш пример с &&может быть эквивалентно перефразирован как

if sudo apt-get update ; then
    sudo apt-get install pyrenamer
fi

Благодарю. Я обновил вопрос, чтобы убедиться, что различные подвопросы легко различимы.
don.joey

5
@Private: Вы должны использовать, ;если вторая команда не нуждается в предыдущей для успеха.
Чороба

31

Использование ;выполнит команды независимо от того, успешна ли первая команда или нет.

использовать &&команду «Выполнить 2-ю команду» только в случае успешного выполнения первой команды (статус 0)

Оба используются с разных точек зрения. Как для более длительного процесса, скажем, для установки вам нужно скомпилировать и установить его. ты должен make && make install. Таким образом, установка будет выполняться только в случае makeуспеха.

Так что для зависимых команд вы должны использовать &&

Wring bash или команды с независимыми командами ;

Поэтому, если вы хотите выключить компьютер, даже если первое задание не удалось использовать ;, но если вы хотите, чтобы первое задание было завершено успешно, запустите отключение.&&


14

a ; bбудет работать b независимо от состояния выхода a. a && bбудет работать только в случае успеха.

Это необходимо и достаточно, чтобы ответить на первые 3 вопроса. В частности, цифра 2 слишком широка, и на нее нельзя дать однозначный однозначный ответ - лучше всего выбирать для каждого конкретного случая.

Что касается 4-го вопроса: это синтаксис Bash .

Там нет никакой внутренней опасности в использовании либо. Опять же, приведенного выше определения достаточно. Это означает, что вы будете писать, &&когда bимеет непредвиденные последствия, если aне удастся. Нет необходимости в дополнительных правилах или объяснениях, ИМХО.


1

A; B # Запустите A, а затем B, независимо от успеха A

A && B # Выполнить B, если и только если успешно

A || B # Выполнить B, если и только если A не удалось

A & # Run A в фоновом режиме.

Очень хорошее эмпирическое правило. Я бы добавил, что в некоторых случаях использование этих команд в подоболочке имеет смысл, когда мы хотим рассматривать их как единое целое или не хотим связывать некоторые результаты операций с текущей оболочкой.

Примеры:

-связать вывод двух команд:

(ls foo; ls bar) > single-result.txt

-входя в каталог и выполняя команду оттуда, не меняя текущий каталог оболочки:

(cd target-directory && jar -xf ../my-jar)
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.