Скрипт Bash не работает с `sh`
Я тестирую простой скрипт, и мне интересно, почему он работает нормально при выполнении из каталога: ./test.sh
но когда я пытаюсь с командой "sh" sh test.sh
это не работает:
test.sh: 3: test.sh: [[: not found
test.sh: 7: test.sh: [[: not found
Автор сценария:
#!/usr/bin/env bash
if [[ $1 = one ]]
then
printf "%b" "two\n" >&2
exit 0
elif [[ $1 = two ]]
then
printf "%b" "one\n" >&2
exit 0
else
printf "%b" "Specify argument: one/two\n"
exit 1
fi
2 ответа
Резюме
sh
это другая программа, чем bash
,
подробность
Проблема в том, что оболочка Борна (sh
) это не оболочка Bourne Again (bash
). А именно, Ш не понимает [[
Прагма. На самом деле, он не понимает [
или. [
является актуальной программой или ссылкой на /bin/test (или /usr/bin/[, /usr/bin/test).
$ which [
/bin/[
$ ls -lh /bin/[
-r-xr-xr-x 2 root wheel 42K Feb 29 17:11 /bin/[
Когда вы выполняете свой скрипт напрямую через ./test.sh
Вы вызываете скрипт как первый аргумент для программы, указанной в первой строке. В этом случае:
#!/usr/bin/env bash
Часто это прямо переводчик (/bin/bash
или любое другое число интерпретаторов сценариев), но в вашем случае вы используете env для запуска программы в измененной среде - но следующий аргумент по-прежнему bash. Эффективно, ./test.sh
является bash test.sh
,
Так как sh
а также bash
разные оболочки с разными синтаксическими интерпретациями, вы видите эту ошибку. Если вы бежите bash test.sh
, вы должны увидеть, что ожидается.
Больше информации
Другие отметили в комментариях, что /bin/sh
может быть ссылкой или другой оболочкой. Исторически, sh
была оболочкой Bourne на старом AT&T Unix и, на мой взгляд, каноническим спуском. Однако, это отличается в вариациях BSD и со временем расходится в других системах и дистрибутивах на основе Unix. Если вы действительно заинтересованы во внутренней работе (включая то, как /bin/sh и /bin/bash могут быть одной и той же программой и вести себя совершенно по-разному), прочитайте следующее:
Как уже отмечалось: /bin/sh обычно (хотя и не всегда) вызывает POSIX-совместимую оболочку Bourne. Баш не Борн.
Bash будет пытаться эмулировать Bourne, когда вызывается как 'sh' (например, когда символические ссылки / bin / sh или ссылки на /bin/bash), или если $POSIXLY_CORRECT определен в среде вызова, когда вызывается с опцией вызова --posix, или когда был выполнен "set -o posix". Это позволяет протестировать скрипт / команду оболочки Bourne на соответствие POSIX.
Альтернативно, вызовите скрипты / команды тестирования с известной POSIX-совместимой оболочкой. 'dash' близок, оболочка Korn (ksh) IIRC также предлагает POSIX-совместимую опцию.