&& или ; в терминале — в чём разница и почему один символ выкатывает сломанный код

Агент написал команду npm test; git push. Тесты упали. Код всё равно ушёл на сервер.
Ошибки в логике нет. Есть один символ. С && вместо ; ничего бы не отправилось.
В чём разница между && и ;
Оба соединяют команды в одну строку. Разница в том, что происходит после первой:
- Когда запускается вторая команда.
;— всегда, что бы ни случилось.&&— только если первая завершилась успешно, то есть с кодом выхода 0. - Что видно по итогу. У обеих результат цепочки — код последней выполненной команды. Но
false; echo okвернёт 0: провал спрятался. Аfalse && echo okвернёт 1. - Где работает.
;работает почти везде.&&работает в bash, zsh, cmd и PowerShell 7. В старом Windows PowerShell 5.1 его нет: будет ошибкаThe token '&&' is not a valid statement separator. - Для чего.
;— для независимых команд.&&— для шагов, где следующий имеет смысл только после предыдущего.
Проверь сам, это безопасно:
$ false && echo A; echo B
B
$ false; echo C
C
Первая строка не напечатала A: && остановился. Но B напечатано, потому что после ; цепочка начинается заново.
Где ; действительно опасен
Посмотри на такую строку:
cd build; rm -rf *
Папки build нет. cd падает с ошибкой. ; на это не смотрит и запускает rm дальше — в той папке, где ты стоишь. Я проверил безопасную версию этого сценария:
$ cd /nonexistent; pwd
bash: cd: /nonexistent: No such file or directory
/tmp/lab
pwd показал папку, из которой мы никуда не ушли. Вместо pwd могло стоять что угодно. С && такая строка просто остановилась бы:
cd build && rm -rf ./*
Ещё одна деталь: rm -rf ./* безопаснее, чем rm -rf *, — файл с именем -rf не примется за флаг.
Кому что подойдёт
Вердикт простой: по умолчанию пиши &&.
Бери &&, если шаги зависят друг от друга. Это почти все случаи: npm install && npm run build, cd app && npm test, git pull && git push.
Бери ;, только когда вторая команда нужна в любом случае. Например, напомнить себе, что сборка кончилась, чем бы она ни закончилась:
npm run build; echo "Сборка закончилась"
Просишь ИИ-агента запускать команды — впиши это в инструкцию проекта: «шаги соединяй через &&». Правило занимает одну строку, а выкатку сломанного кода предотвращает.
А как же || и &
У && есть два родственника, и их часто путают.
|| — запусти, если первая упала. Удобно для запасного плана:
cd nope && echo fine || echo fallback
# bash: cd: nope: No such file or directory
# fallback
Запись a && b || c похожа на if-else, но им не является. Если b упадёт, c тоже запустится:
$ true && false || echo z
z
Один & — запуск в фоне. Это совсем другое: команда уходит работать сама, а терминал сразу свободен. npm test & git push запустит оба параллельно. Лишний или недостающий символ здесь меняет смысл полностью.
Где ты это встретишь
- Dockerfile.
RUN apt-get update && apt-get install -y curl— канонический пример. Упадёт первый шаг, упадёт и сборка образа. Подробнее — в статье что такое Docker. - CI. На Linux-раннерах GitHub Actions запускает
bash -e. Поэтому там;тоже обрывает шаг при падении. Но только там: локально этого страховочного троса нет. Про сам CI — в статье что такое CI/CD. - Скрипты. В файле перенос строки работает как
;: упавшая строка не остановит следующую. Поставьset -eв начале, и скрипт будет останавливаться на первой ошибке.
Что писать в Windows PowerShell 5.1?
Простой обходной путь — npm test; if ($?) { git push }. Переменная $? хранит, успешно ли прошла предыдущая команда. Или поставь PowerShell 7, там && работает как в bash.
Перенос строки — это то же самое, что ;?
Да. Две команды на двух строках ведут себя как a; b. Поэтому в скриптах и нужен set -e.
А cmd.exe понимает &&?
Понимает. Там && работает как в bash, а одиночный & значит просто «потом», а не запуск в фоне.
Короткие уроки-истории, симулятор агента и ежедневная практика — в нашем мобильном приложении. Бесплатно.





