Точка с запятой или двойной амперсанд для цепочки команд? [dубликат]

Этот вопрос уже имеет ответ здесь: какой из них лучше: использование; или & amp; & amp; выполнить несколько команд в одной строке? 4 ответа Как объединить несколько команд в терминале? 1 ответ

При написании сценария bash, который лучше всего связывает команды, точка с запятой ; или двойной амперсанд &&?

0
задан 21 April 2018 в 13:56

2 ответа

Как говорит steeldriver, ни один не лучше другого. Вы используете их для разных целей.

Используйте ;, если вы хотите запустить одну команду, затем другую. Вторая команда будет выполняться независимо от того, удастся ли ей выполнить первую. Разделение команд с помощью ; достигает той же цели, что и выполнение одной команды, а затем запуск другой. В сценарии они достигают той же цели:

first-command second-command first-command; second-command

Напротив, && проверяет статус выхода первой команды и выполняет только вторую команду, если первая команда выполнена успешно. В сценариях оболочки (и когда вы используете оболочку в интерактивном режиме тоже), код выхода 0 принимает значение «true» или «success», в то время как любой другой код выхода воспринимается как «false» или «failure» «. (Таким образом, программы могут возвращать разные коды ошибок, чтобы обозначать разные типы ошибок.)

Итак, здесь, как и прежде, выполняется first-command. Но если это не удается, то second-command не запускается вообще:

first-command && second-command

Это похоже на, но не совсем то же самое, что и при использовании if:

if first-command; then second-command fi

То, как они отличаются, заключается в том, что происходит, когда first-command терпит неудачу. С && статус выхода всей составной команды - это какой-либо отказ (то есть ненулевой) код выхода first-command. В отличие от if, состояние выхода всей составной команды равно нулю (т. Е. Успех), когда first-command терпит неудачу.

В качестве примера ситуации, в которой вы могли бы на самом деле разумно рассмотреть как ;, так и &&, предположим, что вы хотели запустить sudo apt update, который извлекает самую последнюю информацию о том, какие пакеты доступны из каждого из ваших настроенных источников программного обеспечения и в каких версиях, а затем sudo apt upgrade, чтобы обновить установленные пакеты до их последних доступных версий. Это широко предлагается и я обычно запускаю:

sudo apt update && sudo apt upgrade

Поскольку он использует &&, он запускает sudo apt update, но работает только sudo apt upgrade, если sudo apt update сообщил, что он преуспел. Причина, по которой вы обычно хотели бы этого, в случае этих конкретных команд, состоит в том, что вы обычно хотели бы проверить любые ошибки, которые первая команда произвела, чтобы решить, как действовать.

Но вы можете ожидать проблема, но все же хотите обновить какие пакеты вы могли бы. Или вы можете не ожидать проблемы, но просто предпочтете продолжить движение в любом случае. В этой ситуации вы можете разделить их на ; (или просто поместить их в отдельные строки в сценарии):

sudo apt update; sudo apt upgrade

Выполняется sudo apt update, затем запускает sudo apt upgrade независимо от того, или нет, он сообщил о достижении успеха.

Это работает как пример ситуации, когда вы действительно можете выбирать между ними, потому что это случай, когда первая команда важна для второй, но где второй может быть полезен, даже если первый из них не удался. Тем не менее, во многих ситуациях, когда вы хотите запустить одну команду, а затем другую, вы либо имеете:

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

Кстати, есть и оператор ||. Эта команда выполняет вторую команду только в том случае, если первая команда в случае этих конкретных команд , а не только, если она преуспела (как &&):

first-command || second-command

|| не следует путать с |, который устанавливает трубку между командами.

6
ответ дан 17 July 2018 в 16:28

Как говорит steeldriver, ни один не лучше другого. Вы используете их для разных целей.

Используйте ;, если вы хотите запустить одну команду, затем другую. Вторая команда будет выполняться независимо от того, удастся ли ей выполнить первую. Разделение команд с помощью ; достигает той же цели, что и выполнение одной команды, а затем запуск другой. В сценарии они достигают той же цели:

first-command second-command first-command; second-command

Напротив, && проверяет статус выхода первой команды и выполняет только вторую команду, если первая команда выполнена успешно. В сценариях оболочки (и когда вы используете оболочку в интерактивном режиме тоже), код выхода 0 принимает значение «true» или «success», в то время как любой другой код выхода воспринимается как «false» или «failure» «. (Таким образом, программы могут возвращать разные коды ошибок, чтобы обозначать разные типы ошибок.)

Итак, здесь, как и прежде, выполняется first-command. Но если это не удается, то second-command не запускается вообще:

first-command && second-command

Это похоже на, но не совсем то же самое, что и при использовании if:

if first-command; then second-command fi

То, как они отличаются, заключается в том, что происходит, когда first-command терпит неудачу. С && статус выхода всей составной команды - это какой-либо отказ (то есть ненулевой) код выхода first-command. В отличие от if, состояние выхода всей составной команды равно нулю (т. Е. Успех), когда first-command терпит неудачу.

В качестве примера ситуации, в которой вы могли бы на самом деле разумно рассмотреть как ;, так и &&, предположим, что вы хотели запустить sudo apt update, который извлекает самую последнюю информацию о том, какие пакеты доступны из каждого из ваших настроенных источников программного обеспечения и в каких версиях, а затем sudo apt upgrade, чтобы обновить установленные пакеты до их последних доступных версий. Это широко предлагается и я обычно запускаю:

sudo apt update && sudo apt upgrade

Поскольку он использует &&, он запускает sudo apt update, но работает только sudo apt upgrade, если sudo apt update сообщил, что он преуспел. Причина, по которой вы обычно хотели бы этого, в случае этих конкретных команд, состоит в том, что вы обычно хотели бы проверить любые ошибки, которые первая команда произвела, чтобы решить, как действовать.

Но вы можете ожидать проблема, но все же хотите обновить какие пакеты вы могли бы. Или вы можете не ожидать проблемы, но просто предпочтете продолжить движение в любом случае. В этой ситуации вы можете разделить их на ; (или просто поместить их в отдельные строки в сценарии):

sudo apt update; sudo apt upgrade

Выполняется sudo apt update, затем запускает sudo apt upgrade независимо от того, или нет, он сообщил о достижении успеха.

Это работает как пример ситуации, когда вы действительно можете выбирать между ними, потому что это случай, когда первая команда важна для второй, но где второй может быть полезен, даже если первый из них не удался. Тем не менее, во многих ситуациях, когда вы хотите запустить одну команду, а затем другую, вы либо имеете:

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

Кстати, есть и оператор ||. Эта команда выполняет вторую команду только в том случае, если первая команда в случае этих конкретных команд , а не только, если она преуспела (как &&):

first-command || second-command

|| не следует путать с |, который устанавливает трубку между командами.

6
ответ дан 23 July 2018 в 17:20
  • 1
    Полезным примером является следующий «однострочный», чтобы проверить, загружен ли компьютер в режиме UEFI или BIOS (alias legacy): test -d /sys/firmware/efi && echo efi || echo bios – sudodus 20 April 2018 в 23:15
  • 2
    @sudodus Вы можете использовать это, но я не считаю это хорошей техникой. Я рекомендую не пытаться использовать && и || как тернарный условный. Часто вторая команда может выйти из строя; то третий работает. Даже echo может выйти из строя, например, если stdout не доступен для записи (вы можете перенаправить на /dev/full, чтобы имитировать это). В этой команде, если echo efi терпит неудачу, то echo bios должен [] d0] также выйти из строя. Но представьте себе, если вы заменили echo bios тем, что имело другие эффекты! Даже когда нет риска, он плохо документирует себя, поскольку a && b || c не достигает тернарной условной семантики вне таких угловых случаев. – Eliah Kagan 20 April 2018 в 23:39
  • 3
    @sudodus. Основываясь на команде, которую вы показали, ls -ld /sys/firmware/efi более компактна и понятна в отношении того, что она делает; сказать, как интерпретировать его вывод - объяснить, как работает тест. Однако, если ваша конкретная цель - напечатать efi, когда система загружается в режиме UEFI и bios, когда она загружается в режиме BIOS, и вам нужно сделать это в однострочном пространстве, тогда я бы предпочел if [ -d /sys/firmware/efi ]; then echo efi; else echo bios; fi. Это длиннее, но оно все еще удобно помещается на одной линии, и его смысл предельно ясен. Читателям не нужно учитывать статус выхода echo efi. – Eliah Kagan 21 April 2018 в 14:06
  • 4
    @sudodus и EliahKagan a && { b ; : ;} || c обеспечивают возможное обходное решение проблемы: группа всегда возвращает 0 независимо от того, сработала ли b. Как насчет test -d /sys/firmware/efi && { echo efi; : ;} || echo bios? – dessert 23 April 2018 в 10:02
  • 5
    @dessert, Да, это тоже работает :-) Но мы должны согласиться с EliahKagan, что выражение «if then else fi» легче понять, чем логика «& amp; & amp; и || '. – sudodus 23 April 2018 в 10:07

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

Похожие вопросы: