$? после &&, || и if: почему код возврата Bash бывает неочевидным
В Bash $? содержит код завершения последней выполненной команды. Но конструкции &&, || и if меняют то, какие команды вообще выполняются.
▪️Простая цепочка
false && echo "OK"
echo $?
echo после && не запускается, потому что false вернула 1.
Итоговый $? - 1.
А здесь:
true && echo "OK"
echo $?
последней командой становится echo "OK", поэтому $? уже равен 0.
▪️С || ситуация аналогичная
false || echo "fallback"
echo $?
false запускается, затем выполняется echo, потому что первая команда завершилась ошибкой.
В итоге $? будет 0 - код echo, а не false.
Если нужен исходный результат:
false
status=$?
if [ "$status" -ne 0 ]; then
echo "Command failed: $status"
fi
▪️Почему if не создаёт обычный 1
if false; then
echo "success"
fi
echo $?
Здесь if возвращает статус последней выполненной команды в выбранной ветке. Если ни одна ветка не выполнялась, результатом становится код проверки условия.
▪️Частая ошибка
command || echo "failed"
status=$?
status здесь содержит результат echo, а не command.
Если важно сохранить код ошибки:
if ! command; then
status=$?
fi
Но здесь есть ещё один нюанс: ! инвертирует статус, поэтому для получения исходного кода лучше сохранять его непосредственно после команды.
Например:
command
status=$?
if [ "$status" -ne 0 ]; then
echo "failed: $status"
fi
▪️Почему это важно
В сложных Bash-скриптах $? легко прочитать слишком поздно. Любая следующая команда - даже echo, printf или test - может заменить предыдущий код возврата.
Поэтому если результат команды важен, сохраняйте его сразу.
BashTex 📱 #bash #linux
В Bash $? содержит код завершения последней выполненной команды. Но конструкции &&, || и if меняют то, какие команды вообще выполняются.
▪️Простая цепочка
false && echo "OK"
echo $?
echo после && не запускается, потому что false вернула 1.
Итоговый $? - 1.
А здесь:
true && echo "OK"
echo $?
последней командой становится echo "OK", поэтому $? уже равен 0.
▪️С || ситуация аналогичная
false || echo "fallback"
echo $?
false запускается, затем выполняется echo, потому что первая команда завершилась ошибкой.
В итоге $? будет 0 - код echo, а не false.
Если нужен исходный результат:
false
status=$?
if [ "$status" -ne 0 ]; then
echo "Command failed: $status"
fi
▪️Почему if не создаёт обычный 1
if false; then
echo "success"
fi
echo $?
Здесь if возвращает статус последней выполненной команды в выбранной ветке. Если ни одна ветка не выполнялась, результатом становится код проверки условия.
▪️Частая ошибка
command || echo "failed"
status=$?
status здесь содержит результат echo, а не command.
Если важно сохранить код ошибки:
if ! command; then
status=$?
fi
Но здесь есть ещё один нюанс: ! инвертирует статус, поэтому для получения исходного кода лучше сохранять его непосредственно после команды.
Например:
command
status=$?
if [ "$status" -ne 0 ]; then
echo "failed: $status"
fi
▪️Почему это важно
В сложных Bash-скриптах $? легко прочитать слишком поздно. Любая следующая команда - даже echo, printf или test - может заменить предыдущий код возврата.
Поэтому если результат команды важен, сохраняйте его сразу.
BashTex 📱 #bash #linux