Если вам нужно только знать, была ли команда выполнена успешно или с ошибкой, не утруждайте себя тестированием $?, просто протестируйте команду напрямую. например.:
if some_command; then printf 'some_command succeeded\n'else printf 'some_command failed\n'fi
И присвоение выходных данных переменной не изменяет возвращаемое значение (ну, если, конечно, оно не ведет себя по-другому, когда stdout не является терминалом).
if output=$(some_command); then printf 'some_command succeded, the output was «%s»\n' "$output"fi
в большинстве случаев проще использовать конструкцию && для цепочки команд, которые должны зависеть друг от друга. Так cd /nonexistant && echo success! было бы нет повторите успех, потому что команда прерывается перед &&. Следствием этого является ||, где cd /nonexistant || echo failбыло бы ошибка echo из-за сбоя компакт-диска. (это становится полезным, если вы используете что-то вроде ||exit, которое завершит сценарий, если предыдущая команда завершилась неудачно.)
Следует отметить, что if...then...fi и &&/|| тип подхода имеет дело со статусом выхода, возвращаемым командой, которую мы хотим протестировать (0 при успешном выполнении); однако некоторые команды не возвращают ненулевой статус выхода, если команда завершилась неудачно или не смогла обработать ввод. Это означает, что обычный if и &&/|| подходы не будут работать для этих конкретных команд.
Например, в Linux GNU file по-прежнему завершается с 0, если он получил несуществующий файл в качестве аргумента и find не удалось найти указанный пользователем файл.
$ find . -name "not_existing_file" $ echo $?0$ file ./not_existing_file ./not_existing_file: cannot open `./not_existing_file' (No such file or directory)$ echo $?0
В таких случаях один из возможных способов, которым мы могли бы справиться с ситуацией, - это прочитать stderr/stdin сообщения, например, те, которые возвращены file команду или проанализируйте вывод команды, как в find. Для этих целей, case заявление может быть использовано.
$ file ./doesntexist | while IFS= read -r output; do > case "$output" in > *"No such file or directory"*) printf "%s\n" "This will show up if failed";;> *) printf "%s\n" "This will show up if succeeded" ;;> esac> doneThis will show up if failed$ find . -name "doesn'texist" | if ! read IFS= out; then echo "File not found"; fi File not found
Как упоминалось во многих других ответах, простой тест на $? будет делать, как это
if [ $? -eq 0 ]; then something; fi
Если вы хотите проверить, выполняется ли команда провалившийся, вы можете использовать более короткую версию в bash (но, возможно, излишне) следующим образом:
if (($?)); then something; fi
Это работает с помощью (( )) арифметический режим, так что если команда вернет success, то есть $? = 0 затем тест оценивается как ((0)) который проверяет как false, в противном случае он вернется true.