Этот вопрос часто был номинирован как канонический для людей, которые пытаются использовать sh
, и удивляются, что он не ведет себя так же, как bash
. Вот краткое описание распространенных недоразумений и ошибок.
Во-первых, вы должны понимать, чего ожидать.
sh scriptname
или запустите его с scriptname
и #!/bin/sh
в строке shebang , вы должны ожидать поведение POSIX sh
. bash scriptname
или запустите его с scriptname
и иметь #!/bin/bash
(или локальный эквивалент) в строке shebang, вы должны ожидать поведения Bash. Имея правильный shebang и запуская скрипт, набрав только скрипт имя (возможно, с относительным или полным путем), как правило, является предпочтительным решением. В дополнение к правильному shebang для этого требуется, чтобы файл сценария имел разрешение на выполнение (chmod a+x scriptname
).
Итак, как они на самом деле отличаются?
Справочное руководство Bash содержит , который пытается перечислить различия , но некоторые общие источники путаницы включают
[[
, недоступны в sh
(только [
, который является более неуклюжим и ограничено). sh
не имеет массивов. local
, function
и select
, не переносимы на sh
. $'string\nwith\tC\aescapes'
и три аргумента for((i=0;i<=3;i++))
, [increment assign] +=
и т. д. <<<'here strings'
. *.{png,jpg}
и {0..9}
. ~
относится к $HOME
только в Bash (и, в более общем смысле, ~username
в домашний каталог username
). <(cmd)
и >(cmd)
. <>
. ${substring:1:2}
, ${variable/pattern/replacement}
, преобразования case и т. д. Помните, что это сокращенный список , Обратитесь к справочному руководству для полного совка и http://mywiki.wooledge.org/Bashism для многих хороших обходных решений; и / или попробуйте http://shellcheck.net/ , который предупреждает обо всех возможностях Bash.
Общей ошибкой является наличие строки #!/bin/bash
shebang, но затем тем не менее, используя sh scriptname
для фактического запуска скрипта. Это в основном отключает любую функцию Bash-only, поэтому вы получаете синтаксические ошибки, например. для попытки использования массивов.
К сожалению, Bash не будет предупреждать, когда вы пытаетесь использовать эти конструкции, когда он вызывается как sh
. Это не полностью отключает все функции Bash-only, так что запуск Bash путем вызова его как sh
не является хорошим способом проверить, правильно ли ваш сценарий переносится на ash
/ dash
/ POSIX sh
.