sh和bash之间的区别


1303

在编写Shell程序时,我们经常使用/bin/sh/bin/bash。我通常使用bash,但是我不知道它们之间有什么区别。

bash和之间的主要区别是sh什么?

bash和中进行编程时,我们需要注意sh什么?


21
有关可以在Bourne shell上运行的bashism和相应代码的有用列表,请参见mywiki.wooledge.org/Bashism
StackExchange saddens dancek 2011年

1
您可能希望看到POSIX的SH标准的命令语言:* SH * shell命令行语言
毛里西奥ç安栋梁

7
一般而言,由于所有pos脚本都具有posix兼容性,因此所有sh脚本都将在bash下运行,但并非所有bash脚本都可以在sh下运行,您注意到的主要区别是[[]]而不是[]比较,该比较允许未加引号的空格, $(())而不是$ []算术表达式,以及诸如bash docs中的“它太大而又太慢”之类的其他信息。但是,新脚本编写者不必将自己限于与sh兼容的脚本,除非它们正在为某些脚本射击向后兼容,这些天来往往不是这种情况,毕竟是(或曾经是)2014年吧?
osirisgothra 2014年

Answers:


1140

什么是嘘

sh(或Shell命令语言)是POSIX标准描述的一种编程语言。它有许多的实现(ksh88dash,...)。bash也可以视为的实现sh(请参见下文)。

因为sh是规范,而不是实现,所以它/bin/sh是到大多数POSIX系统上实际实现的符号链接(或硬链接)。

什么是bash

bash开始时是一个sh兼容的实现(尽管它比POSIX标准早了几年),但是随着时间的流逝,它获得了许多扩展。这些扩展中的许多扩展名可能会更改有效POSIX Shell脚本的行为,因此,它本身bash不是有效的POSIX Shell。相反,它是POSIX Shell语言的方言。

bash支持一个--posix开关,这使其更符合POSIX。如果以调用,它也会尝试模仿POSIX sh

sh =重击?

长期以来,/bin/sh它一直指向/bin/bash大多数GNU / Linux系统。结果,几乎可以忽略两者之间的区别了。但是这种情况最近开始改变。

/bin/sh不指向/bin/bash(某些/bin/bash甚至可能不存在)的系统的一些流行示例是:

  1. 现代Debian和Ubuntu系统,默认情况下符号链接shdash
  2. Busybox,通常在Linux系统启动期间作为的一部分运行initramfs。它使用ashshell实现。
  3. BSD,通常是任何非Linux系统。OpenBSD使用pdkshKorn shell的后代。FreeBSD sh是原始UNIX Bourne shell的后代。Solaris具有自己的sh名称,长期以来不兼容POSIX。Heirloom项目提供了免费的实现。

您如何找出/bin/sh系统上的指向?

复杂之处在于它/bin/sh可能是符号链接或硬链接。如果它是符号链接,则一种可解决的便携式方法是:

% file -h /bin/sh
/bin/sh: symbolic link to bash

如果是硬链接,请尝试

% find -L /bin -samefile /bin/sh
/bin/sh
/bin/bash

实际上,该-L标志涵盖了符号链接和硬链接,但是此方法的缺点是它不可移植-POSIX 不需要 find支持该-samefile选项,尽管GNU findFreeBSD find都支持该选项。

社bang线

最终,由您决定要使用哪个脚本,方法是将“ shebang”行写为脚本的第一行。

例如

#!/bin/sh

将使用sh(以及碰到的任何东西),

#!/bin/bash

/bin/bash在可用的情况下使用(如果不可用,则会失败并显示错误消息)。当然,您也可以指定其他实现,例如

#!/bin/dash

使用哪一个

对于我自己的脚本,sh出于以下原因,我更喜欢:

  • 它是标准化的
  • 它更容易学习
  • 它可以跨POSIX系统移植-即使它们恰好没有bash,也必须具有sh

使用也有好处bash。它的功能使编程更加方便,并且类似于其他现代编程语言中的编程。这些包括范围局部变量和数组之类的东西。Plain sh是一种非常简约的编程语言。


如果您以bash显示方式运行脚本,则在语法错误的情况下会显示更多有用的错误消息。您只需使用bash即可节省时间。
PHPst

%命令行开头是什么意思?
JosephHarriott

@JosephHarriott是一个提示:一个由外壳本身打印的字符,在此之后您执行命令。某些外壳程序使用$代替%,或将其#用作根外壳程序。
Roman Cheplyaka

@RomanCheplyaka哪个贝壳?我只看过$#...
JosephHarriott

@RomanCheplyaka我敢肯定sh,bash之前就已经存在(代表bourne-again shell)。但这是非常原始的,并且不会响应终端事件,例如ESC字符。然后ksh来了(也就是在bash之前),然后bash由那些喜欢更好的shell但讨厌ksh的人开始。:-)
raminr

145

shhttp
bash : //man.cx/shhttp : //man.cx/bash

TL; DRbashsh具有更优雅的语法和更多功能的超集。在几乎所有情况下,使用bash shebang行都是安全的,因为它在现代平台上非常普遍。

注意:在某些环境中sh bash。检查sh --version


31
如果bash作为sh调用,则其行为会有所不同。请参阅gnu.org/software/bash/manual/bashref.html#Bash-Startup-Files(“使用名称sh调用”)和gnu.org/software/bash/manual/bashref.html#Bash-POSIX-Mode。例如,没有进程替代。
glenn jackman 2011年

11
由于bash是sh的超集,并且某些操作系统(例如FreeBSD)默认未安装bash,因此sh中的脚本编写将提供更大的可移植性。
user674062 2011年

1
由于没有可移植的脚本化方法来获取特定脚本的POSIX Shell,因此可移植的脚本不能承担Bourne Shell的更多功能。
schily

83

对于试图使用该问题的人,该问题经常被提名为规范问题sh,但对此感到惊讶的是,它的行为与相同bash。这是常见误解和陷阱的快速清单。

首先,您应该了解期望。

  • 如果你运行你的脚本sh scriptname,或运行它scriptname,并有#!/bin/sh家当行,你应该期望POSIX sh的行为。
  • 如果使用来运行脚本bash scriptname,或者使用来运行脚本,scriptname#!/bin/bash在shebang行中使用(或等效于本地的)脚本,则应该期望Bash行为。

通常,首选解决方案是使用正确的shebang并通过仅键入脚本名称(可能使用相对路径或完整路径)来运行脚本。除了正确的Shebang之外,这还要求脚本文件具有执行权限(chmod a+x scriptname)。

那么,它们实际上有何不同?

《 Bash参考手册》的一部分试图枚举差异,但一些常见的混淆源包括

  • [[不可用sh(仅[笨重且受限)。
  • sh 没有数组。
  • 有些猛砸的关键字时localsourcefunctionshoptletdeclare,和select无法移植到sh。(某些sh实现支持local。)
  • Bash具有许多C样式的语法扩展,例如三参数for((i=0;i<=3;i++))循环,+=增量分配等。该$'string\nwith\tC\aescapes'功能暂时被POSIX接受(这意味着该功能现在在Bash中有效,但sh仅遵循当前规范的系统尚不支持该功能。 POSIX规范,并且很可能在一段时间内不会发布)。
  • Bash支持<<<'here strings'
  • 猛击已经*.{png,jpg}{0..12}支撑扩张。
  • ~$HOME仅在Bash中引用(更普遍~username地是指的主目录username)。这在POSIX中,但是在某些POSIX之前的/bin/sh实现中可能会丢失。
  • Bash可以使用<(cmd)和替换进程>(cmd)
  • Bash具有Csh样式的便捷重定向别名,例如&|for 2>&1 |&>for> ... 2>&1
  • Bash支持带有<>重定向的协同进程。
  • bash实现一组丰富的扩展的非标准参数扩展等的${substring:1:2}${variable/pattern/replacement},大小写转换等
  • Bash大大扩展了Shell算术的功能(尽管仍然没有浮点支持)。有一种过时的旧式$[expression]语法,但是应替换为POSIX算术$((expression))语法。(不过,某些旧的POSIX之前的sh实现可能不支持此功能。)
  • 魔术变量,如$RANDOM$SECONDS$PIPESTATUS[@]$FUNCNAME是Bash的扩展。
  • export variable=value和一样的语法差异[ "x" == "y" ]不可移植(export variable应与变量赋值分开,并且可移植字符串比较[ ... ]使用单个等号)。
  • 许多,仅Bash的扩展用于启用或禁用可选行为并公开Shell的内部状态。
  • 用于交互使用的许多便利功能,但这并不影响脚本行为。

请记住,这是一个简短的清单。有关完整的信息,请参考参考手册;有关许多好的解决方法,请参见http://mywiki.wooledge.org/Bashism。和/或尝试http://shellcheck.net/,它会警告许多仅Bash功能。

一个常见的错误是有一个#!/bin/bashshebang行,但是仍然使用它sh scriptname来实际运行脚本。这基本上会禁用任何仅Bash的功能,因此会出现语法错误,例如,尝试使用数组。(shebang行在语法上是注释,因此在这种情况下,它只是被忽略。)

不幸的是,当您尝试以Bash调用这些构造时,Bash不会发出警告sh。它也不会完全禁用所有仅Bash的功能,因此,通过调用它来运行Bash sh并不是检查脚本是否可正确移植到ash/ dash/ POSIX shHeirloom等变体的好方法sh


2
从根本上讲,TL; DR版本是And的答案
三胞胎

4
shellcheck.net是我所需要的。非常感谢。
Josh Habdas '18

FWIW,export variable=value由POSIX强制授权:pubs.opengroup.org/onlinepubs/009695399/utilities/export.html。也许它在某些古老的外壳中不可用,但绝对不是bashism。
Roman Cheplyaka

53

Shell是用户和OS之间的接口,用于访问操作系统的服务。它可以是GUI或CLI(命令行界面)。

sh(Bourne sh ell)是一个Shell命令行解释器,用于类似Unix / Unix的操作系统。它提供了一些内置命令。在脚本语言中,我们将解释器表示为#!/bin/sh。它是bash(自由/开放),kash(非自由)之类的其他shell支持最广泛的一种。

ourne 一个增益小号地狱)是一个外壳更换对于Bourne壳。Bash是sh的超集。Bash支持sh。POSIX是一组定义POSIX兼容系统应如何工作的标准。Bash实际上不是POSIX兼容的外壳。在脚本语言中,我们将解释器表示为#!/bin/bash

比喻:

  • Shell就像一个接口或规范或API。
  • sh是实现Shell接口的类。
  • Bash是sh的子类。

在此处输入图片说明


3
我不明白 您已经提到“ Bash是sh的超集”和“ Bash是sh的子类”,这不是相反的说法吗?你能澄清一下吗?
Keerthana Prabhakaran

11
我认为这是要说Bash继承sh(因此,它是OOP的“子类”)并对其进行扩展(因此具有功能的超集)。
tripleee

52

UNIX.COM发布

外壳功能

下表列出了我认为会让您选择一个外壳而不是另一个外壳的大多数功能。它不打算作为权威列表,也不包括每个可能的shell的每个可能的功能。仅当功能在操作系统随附的版本中,或者可以从标准发行版直接编译得到时,才认为该功能在外壳程序中。特别是,下面指定的C shell是SUNOS 4. *上可用的,现在许多供应商都提供tcsh或他们自己的增强型C shell(它们并不总是很明显地表明他们在交付tcsh。

码:

                                     sh   csh  ksh  bash tcsh zsh  rc   es
Job control                          N    Y    Y    Y    Y    Y    N    N
Aliases                              N    Y    Y    Y    Y    Y    N    N
Shell functions                      Y(1) N    Y    Y    N    Y    Y    Y
"Sensible" Input/Output redirection  Y    N    Y    Y    N    Y    Y    Y
Directory stack                      N    Y    Y    Y    Y    Y    F    F
Command history                      N    Y    Y    Y    Y    Y    L    L
Command line editing                 N    N    Y    Y    Y    Y    L    L
Vi Command line editing              N    N    Y    Y    Y(3) Y    L    L
Emacs Command line editing           N    N    Y    Y    Y    Y    L    L
Rebindable Command line editing      N    N    N    Y    Y    Y    L    L
User name look up                    N    Y    Y    Y    Y    Y    L    L
Login/Logout watching                N    N    N    N    Y    Y    F    F
Filename completion                  N    Y(1) Y    Y    Y    Y    L    L
Username completion                  N    Y(2) Y    Y    Y    Y    L    L
Hostname completion                  N    Y(2) Y    Y    Y    Y    L    L
History completion                   N    N    N    Y    Y    Y    L    L
Fully programmable Completion        N    N    N    N    Y    Y    N    N
Mh Mailbox completion                N    N    N    N(4) N(6) N(6) N    N
Co Processes                         N    N    Y    N    N    Y    N    N
Builtin artithmetic evaluation       N    Y    Y    Y    Y    Y    N    N
Can follow symbolic links invisibly  N    N    Y    Y    Y    Y    N    N
Periodic command execution           N    N    N    N    Y    Y    N    N
Custom Prompt (easily)               N    N    Y    Y    Y    Y    Y    Y
Sun Keyboard Hack                    N    N    N    N    N    Y    N    N
Spelling Correction                  N    N    N    N    Y    Y    N    N
Process Substitution                 N    N    N    Y(2) N    Y    Y    Y
Underlying Syntax                    sh   csh  sh   sh   csh  sh   rc   rc
Freely Available                     N    N    N(5) Y    Y    Y    Y    Y
Checks Mailbox                       N    Y    Y    Y    Y    Y    F    F
Tty Sanity Checking                  N    N    N    N    Y    Y    N    N
Can cope with large argument lists   Y    N    Y    Y    Y    Y    Y    Y
Has non-interactive startup file     N    Y    Y(7) Y(7) Y    Y    N    N
Has non-login startup file           N    Y    Y(7) Y    Y    Y    N    N
Can avoid user startup files         N    Y    N    Y    N    Y    Y    Y
Can specify startup file             N    N    Y    Y    N    N    N    N
Low level command redefinition       N    N    N    N    N    N    N    Y
Has anonymous functions              N    N    N    N    N    N    Y    Y
List Variables                       N    Y    Y    N    Y    Y    Y    Y
Full signal trap handling            Y    N    Y    Y    N    Y    Y    Y
File no clobber ability              N    Y    Y    Y    Y    Y    N    F
Local variables                      N    N    Y    Y    N    Y    Y    Y
Lexically scoped variables           N    N    N    N    N    N    N    Y
Exceptions                           N    N    N    N    N    N    N    Y

上表的关键字。

可以使用此shell完成功能。

N功能不存在于外壳中。

F功能只能通过使用shell函数机制来完成。

L必须将readline库链接到外壳中才能启用此功能。

上表说明

1. This feature was not in the original version, but has since become
   almost standard.
2. This feature is fairly new and so is often not found on many
   versions of the shell, it is gradually making its way into
   standard distribution.
3. The Vi emulation of this shell is thought by many to be
   incomplete.
4. This feature is not standard but unofficial patches exist to
   perform this.
5. A version called 'pdksh' is freely available, but does not have
   the full functionality of the AT&T version.
6. This can be done via the shells programmable completion mechanism.
7. Only by specifying a file via the ENV environment variable.

您的表对我没有用,因为它试图比较Bourne Shell的功能和1988年之前的ksh的功能。如果您确实制作了1988年的表,则需要从该表中删除大多数其他外壳-包括bash ,sh和rc。您能解释一下您从何处获得表格的值吗?
schily

1
让我给出一些提示:在1989年Bourne Shell中添加了作业控制,并在2005年将Bourne Shell设置为OpenSource。Korn Shell至少从1988年开始具有流程替代,从1997年起它就是OpenSource。BTW:关于$ ENV的声明是不正确的,$ ENV仅针对交互式shell被读取/执行。
schily


@schily如果您觉得它在任何地方都不正确,请随时对其进行适当的编辑。
SriniV

8
根据揭露的内容,似乎最好删除此答案,因为它本质上是欺诈性的,OP并未真正审核他粘贴的信息。
danno 2015年

24

终奌站

  • 打开窗口的程序
  • xterm,rxvt,konsole,kvt,gnome-terminal,nxterm和eterm。

贝壳

  • 是在终端上运行的程序
  • Shell既是命令解释器又是编程语言
  • 壳牌只是执行命令的宏处理器。
  • 宏处理器意味着将文本和符号扩展以创建更大的表达式的功能。

相对于 重击

SH

  • (贝壳)
  • 是特定的外壳
  • 命令解释器和编程语言
  • BASH的前身

重击

  • (Bourne-Again SHell)
  • 是特定的外壳
  • 命令解释器和编程语言
  • 具有sh功能等
  • SH的继任者
  • BASH是默认的SHELL

参考资料:

外壳 gnu.org:

根本上说外壳程序只是执行命令的宏处理器。术语宏处理器是指将文本和符号扩展以创建更大的表达式的功能。

Unix shell既是命令解释器又是编程语言。 作为命令解释器,shell为丰富的GNU实用程序集提供了用户界面。编程语言功能允许组合这些实用程序。包含命令的文件可以创建,也可以成为命令本身。这些新命令与/ bin等目录中的系统命令具有相同的状态,从而允许用户或组建立自定义环境以自动化其常见任务。

外壳可以交互使用或非交互使用。在交互模式下,它们接受键盘输入的输入。当以非交互方式执行时,shell执行从文件读取的命令。

Shell允许同步和异步执行GNU命令。在接受更多输入之前,shell等待同步命令完成。异步命令继续与外壳程序并行执行,同时读取并执行其他命令。重定向结构允许对这些命令的输入和输出进行细粒度的控制。而且,外壳程序允许控制命令环境的内容。

Shell还提供了一小组内置命令(builtins),这些命令实现了无法或不方便通过单独的实用程序获得的功能例如,cd,break,continue和exec不能在Shell外部实现,因为它们直接操纵Shell本身。历史记录,getopts,kill或pwd内置程序等可以在单独的实用程序中实现,但用作内置命令更方便。后续各节将介绍所有的shell内置程序。

尽管执行命令是必不可少的,但是大多数Shell的功能(和复杂性)都归功于它们的嵌入式编程语言。 像任何高级语言一样,shell提供变量,流控制构造,引用和函数。

Shell提供了专门为交互使用而设计的功能,而不是扩展编程语言。这些交互式功能包括作业控制,命令行编辑,命令历史记录和别名。这些功能中的每一个都在本手册中进行了描述。

BASH gnu.org:

Bash是GNU操作系统的外壳程序或命令语言解释器。该名称是'Bourne-Again SHell'的首字母缩写,它是Stephen Bourne的双关语,Stephen Bourne是当前Unix shell sh的直接祖先的作者,该版本出现在Unix的第七版Bell Labs Research版本中。

Bash在很大程度上与sh兼容,并结合了Korn shell ksh和C shell csh的有用功能。它旨在成为IEEE POSIX规范(IEEE标准1003.1)的IEEE POSIX外壳和工具部分的一致实现。它提供了相对于sh的功能改进,可用于交互和编程。

虽然GNU操作系统提供了其他shell,包括csh版本,但Bash是默认的shell。像其他GNU软件一样,Bash具有很好的可移植性。目前,它几乎可以在Unix的每个版本以及其他一些操作系统上运行-MS-DOS,OS / 2和Windows平台存在独立支持的端口。


14

其他答案通常指出Bash与POSIX Shell标准之间的区别。但是,在编写可移植的shell脚本并使用Bash语法时,非常典型的bashism列表和相应的纯POSIX解决方案非常方便。当Ubuntu从Bash切换为Dash作为默认系统外壳时,已经编译了此类列表,可以在以下位置找到:https : //wiki.ubuntu.com/DashAsBinSh

此外,有一个很棒的工具叫做checkbashisms,它可以检查脚本中的bashisms,并在您要确保脚本可移植时很方便。


基本上,这就是我到目前为止的答案。+1
三胞胎

7

它们几乎相同,但bash具有更多功能sh是(或多或少)是的较旧子集bash

sh通常是指Bourne shell始于bashBourne *again* shell)并于1977年创建的原始文档。但是,在实践中,最好将其视为与1992年的POSIX标准兼容的高度交叉兼容的外壳。

#!/bin/shshShell 开头或使用Shell的脚本通常这样做是为了向后兼容。任何unix / linux操作系统都将具有sh外壳。在Ubuntu上sh经常调用dash,在MacOS上是POSIX的特殊版本bash。对于标准兼容的行为,速度或向后兼容性,这些外壳可能是首选。

bash比原始版本更新sh,添加了更多功能,并试图向后兼容sh。理论上,sh程序应在中运行bashbash在几乎所有的linux / unix计算机上都可用,并且通常默认情况下使用-值得注意的是MacOS默认zsh为Catalina(10.15)。默认情况下,FreeBSD没有bash安装。


sh早于POSIX。这些天,您希望所sh找到的至少与POSIX兼容;但是在旧系统上,这绝不是给定的。POSIX的标准化远不止于shell。实际上,您可能会说操作系统调用和库函数的标准化更为重要。
Tripleee

我删除了有关POSIX的内容,以减少混乱
Ryan Taylor

3

/bin/sh可能会或可能不会调用与相同的程序/bin/bash

sh至少支持POSIX所需的功能(假设实现正确)。它也可能支持扩展。

bash,“ Bourne Again Shell”实现了sh以及bash特定的扩展所必需的功能。完整的扩展程序集太长,无法在此处描述,并且随新版本的发布而变化。差异记录在bash手册中。输入info bash并阅读“ Bash功能”部分(当前版本中的第6部分),或者在线阅读当前文档


sh如果您PATH在当前shell中进行了正确的设置,则只会为您提供POSIX shell。没有为您提供POSIX Shell的已定义PATH名称。
schily

很长一段时间,例如在Solaris上,甚至sh都没有给您POSIX shell的必要。
Tripleee '16

3

bash和sh是两个不同的shell。bash基本上是sh,具有更多功能和更好的语法。大多数命令的工作原理是相同的,但它们是不同的。Bash(bash)是许多可用的(至今仍是最常用的)Unix shell之一。Bash代表“ Bourne Again SHell”,并且是对原始Bourne shell(sh)的替换/改进。

Shell脚本是在任何Shell中编写脚本,而Bash脚本是专门为Bash编写脚本。但是,实际上,除非有问题的shell不是Bash,否则“ shell脚本”和“ bash脚本”通常可以互换使用。

话虽如此,您应该在大多数系统上意识到/ bin / sh是符号链接,并且不会调用sh。在Ubuntu中,/ bin / sh用于链接到bash,这是Linux发行版上的典型行为,但现在已更改为链接到另一个称为dash的shell。我会使用bash,因为这几乎是标准的(或者至少从我的经验来看是最常见的)。实际上,当bash脚本将使用#!/ bin / sh时会出现问题,因为脚本创建者认为链接不一定是bash。


0

尽可能地做到以下 几点:基本了解之后,上面发布的其他评论将更容易理解。

Shell- “ Shell”是一个程序,可促进用户与操作系统(内核)之间的交互。有许多shell实现可用,例如sh,bash,csh,zsh ...等。

使用任何Shell程序,我们将能够执行该Shell程序支持的命令。

巴什 -它来源于 ourne- 一个增益 ELL。使用此程序,我们将能够执行Shell指定的所有命令。另外,我们将能够执行一些专门添加到该程序中的命令。Bash与sh具有向后兼容性。

嘘-从伯恩衍生埃尔。“ sh”支持外壳程序中指定的所有命令。就是说,使用此程序,我们将能够执行Shell指定的所有命令。

欲了解更多信息,做到: - https://man.cx/sh - https://man.cx/bash


要了解POSIX,请阅读Alex的回复, 请检查:stackoverflow.com/a/1780614/1261003
Raihanhbh

我并不是想了解POSIX。我正在审核您的答案,因此,我需要查看它,您的答案会增加价值。我认为没有。
Scratte

我相信这些小的澄清将有助于新手更轻松地理解以上讨论中使用的术语。@Scratte
Raihanhbh

-1

Linux操作系统提供了不同类型的Shell。尽管shell有许多共同的命令,但每种类型都有其独特的功能。让我们研究另一种最常用的外壳。

Sh shell:

Sh shell也称为Bourne Shell。Sh shell是1977年AT&T的Bell Labs的Stephen Bourne为Unix计算机开发的第一个shell。它包含许多脚本工具。

打击壳:

Bash shell代表Bourne Again Shell。Bash shell是大多数linux发行版中的默认shell,并替代Sh Shell(Sh shell也将在Bash shell中运行)。Bash Shell可以执行绝大多数Sh Shell脚本,而无需进行修改,并且还提供命令行编辑功能。


肯·汤普森(Ken Thompson)之前有一个炮弹。Bourne shell在v7 Unix(1979)中正式引入。
Tripleee
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.