Скрипт 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 могут быть одной и той же программой и вести себя совершенно по-разному), прочитайте следующее:

SuperUser: В чем разница между Bash и Sh

Википедия: оболочка Борна

Как уже отмечалось: /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-совместимую опцию.

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