/bin/sh
和/bin/bash
。我通常使用bash
,但是我不知道它们之间有什么区别。 bash
和sh
之间的主要区别是什么?在
bash
和sh
中进行编程时,我们需要注意什么?#1 楼
什么是shsh
(或Shell命令语言)是POSIX 标准描述的一种编程语言。
它具有许多实现(
ksh88
,dash
,...) 。 bash
也可以被视为sh
的实现(请参见下文)。因为
sh
是规范而非实现,所以/bin/sh
是符号链接(或硬链接)到大多数POSIX系统上的实际实现。
什么是bash
bash
开始是与sh
兼容的实现(尽管它比POSIX标准早了几年),但是随着时间的流逝,它获得了许多扩展。这些扩展中的许多扩展名可能会更改有效POSIX Shell脚本的行为,因此bash
本身不是有效的POSIX Shell。相反,它是POSIX Shell语言的方言。bash
支持--posix
开关,这使其更符合POSIX。如果长时间调用sh
,它也会尝试模仿POSIX。sh = bash?
很长一段时间以来,
/bin/sh
在大多数GNU / Linux系统上一直指向/bin/bash
。结果,几乎可以忽略两者之间的区别了。但是,这种情况最近才开始改变。一些常见的系统示例,其中
/bin/sh
不指向/bin/bash
(并且其中某些/bin/bash
甚至不存在)是:现代Debian和Ubuntu系统,默认情况下将
sh
链接到dash
; Busybox,通常在Linux系统启动时作为
initramfs
的一部分运行。它使用ash
shell实现。BSD,以及通常所有非Linux系统。 OpenBSD使用
pdksh
,它是Korn 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 find和FreeBSD find支持它。Shebang行
最终,由您决定要使用哪个脚本,只需将«shebang»行写为脚本的第一行即可。
例如
#!/bin/sh
将使用
sh
(以及碰到的任何东西),#!/bin/bash
将使用
/bin/bash
(如果可用)(如果不可用,则会失败并显示错误消息)。当然,您也可以指定另一种实现,例如#!/bin/dash
要使用哪个实现
对于我自己的脚本,我更喜欢
sh
出于以下原因:它是标准化的
它更简单易学
可跨POSIX系统移植-即使它们恰巧没有
bash
,他们必须具有sh
使用
bash
也有优势。它的功能使编程更加方便,并且类似于其他现代编程语言中的编程。这些包括范围局部变量和数组之类的东西。普通的sh
是一种非常简约的编程语言。评论
如果使用bash运行脚本,则在语法错误的情况下,显示方式会更有用。您只需使用bash即可节省时间。
– PHPst
4月7日22:48
%在命令行开头是什么意思?
– joharr
4月16日下午6:33
@JosephHarriott,这是一个提示:一个由外壳本身打印的字符,在此之后您执行命令。有些外壳程序使用$而不是%或#作为根外壳程序。
–罗马Cheplyaka
4月17日7:09
@RomanCheplyaka哪个贝壳?我只看过$和#...
– joharr
4月17日7:39
@JosephHarriott-%通常是C Shell种类的用户shell提示(例如csh,tcsh)。传统上,#是作为超级用户(根)外壳程序的提示字符保留的,而不管选择了哪个。但是,正如历史/传统观察到的那样,这全都属于普通/典型用法的领域。您可以使用自己喜欢的内容和/或用户可以容忍的内容。 :)谷歌如何
– RichieD
8月12日0:28
#2 楼
sh
:http://man.cx/sh bash
:http://man.cx/bash TL; DR:
bash
是sh
的超集,具有更优雅的语法和更多功能。在几乎所有情况下都可以使用bash shebang行,因为它在现代平台上非常普遍。NB:在某些环境中,
sh
是bash
。检查sh --version
。评论
如果bash作为sh调用,则其行为会有所不同。请参阅gnu.org/software/bash/manual/bashref.html#Bash-Startup-Files(“使用名称sh调用”)和gnu.org/software/bash/manual/bashref.html#Bash-POSIX-Mode。例如,没有进程替代。
–格伦·杰克曼
2011年4月20日4:12
由于bash是sh的超集,并且某些操作系统(如FreeBSD)默认情况下未安装bash,因此sh中的脚本编写将提供更大的可移植性。
–user674062
2011年4月20日下午5:49
由于没有可移植的脚本化方法来获取特定脚本的POSIX Shell,因此可移植的脚本不能承担Bourne Shell的更多功能。
–schily
15年9月12日在21:34
#3 楼
对于尝试使用sh
的人们,这个问题经常被提名为规范问题,但感到惊讶的是,它的表现与bash
不同。这是常见误解和陷阱的快速清单。首先,您应该了解期望的内容。
如果您使用
sh scriptname
运行脚本,或者使用scriptname
运行脚本,并且在其中包含#!/bin/sh
shebang行,您应该期待POSIX sh
的行为。 > 通过输入正确的脚本名称(可能是相对路径或完整路径)来正确地运行脚本并运行脚本通常是首选的解决方案。除了正确的Shebang之外,这还要求脚本文件具有执行权限(
bash scriptname
)。那么,它们实际上有何不同?
《 Bash参考手册》中有一节试图枚举不同之处,但一些常见的混乱原因包括
scriptname
在#!/bin/bash
中不可用(仅chmod a+x scriptname
更笨重且受限制)。另请参见Bash中的单方括号和双方括号之间的区别[[
没有数组。一些Bash关键字,例如
sh
,[
,sh
,local
,source
,function
和shopt
不能移植到let
。 (某些declare
实现支持例如select
。)Bash具有许多C风格的语法扩展,例如三参数
sh
循环,sh
增量分配等。local
功能已被POSIX暂时接受(这意味着它现在在Bash中有效) ,但在仅遵循当前POSIX规范的系统上,尚无法得到for((i=0;i<=3;i++))
的支持,并且可能会在一段时间内不支持。)bash支持
+=
。 。$'string\nwith\tC\aescapes'
仅在Bash中引用sh
(更常见的是在<<<'here strings'
的主目录中引用*.{png,jpg}
)。这在POSIX中存在,但在某些POSIX之前的{0..12}
实现中可能会丢失。Bash用
~
和$HOME
替代了进程。 Bash具有Csh样式的便捷重定向别名,例如
~username
用于username
,/bin/sh
用于<(cmd)
Bash支持带有
>(cmd)
重定向的协同处理。Bash具有丰富的扩展非标准参数集扩展,例如
&|
,2>&1 |
,大小写转换等。Bash大大扩展了Shell算术的功能(尽管仍然不支持浮点)。有一种过时的传统
&>
语法,但是应替换为POSIX算术> ... 2>&1
语法。 (但是,某些旧的POSIX之前的<>
实现可能不支持此功能。)${substring:1:2}
,${variable/pattern/replacement}
,$[expression]
和$((expression))
之类的魔术变量是Bash扩展。sh
和$RANDOM
之类的语法差异不可移植(应该与变量赋值分开,并且在$SECONDS
中的可移植字符串比较使用单个等号)。 ,但许多交互使用的便利功能却不影响脚本行为。请记住,这是一个简短的清单。有关完整的信息,请参考参考手册;有关许多好的解决方法,请参见http://mywiki.wooledge.org/Bashism。和/或尝试http://shellcheck.net/,它会警告许多仅Bash的功能。
一个常见的错误是使用
$PIPESTATUS[@]
的shebang行,但是仍然使用$FUNCNAME
来实际运行脚本。这基本上会禁用任何仅Bash的功能,因此会出现语法错误,例如尝试使用数组。 (从语法上说,shebang行是注释,因此在这种情况下它只是被忽略。)不幸的是,当您尝试使用
export variable=value
来使用这些结构时,Bash不会发出警告。它也不会完全禁用所有仅Bash的功能,因此,通过以[ "x" == "y" ]
身份调用来运行Bash并不是检查脚本是否正确可移植到export variable
/ [ ... ]
/ POSIX #!/bin/bash
或诸如Heirloom sh scriptname
之类的变体的好方法评论
从根本上讲,TL; DR版本是And的答案。
–tripleee
17年8月8日在8:47
shellcheck.net是我所需要的。非常感谢。
–乔什·哈布达斯(Josh Habdas)
18年7月30日在10:33
FWIW,POSIX要求导出变量=值:pubs.opengroup.org/onlinepubs/009695399/utilities/export.html。也许它在某些古老的外壳中不可用,但绝对不是bashism。
–罗马Cheplyaka
4月17日7:15
#4 楼
Shell是用户和OS之间的接口,用于访问操作系统的服务。它可以是GUI或CLI(命令行界面)。sh(Bourne外壳)是用于类似Unix / Unix的操作系统的外壳命令行解释器。它提供了一些内置命令。在脚本语言中,我们将解释器表示为
#!/bin/sh
。它是bash(自由/开放),kash(非自由)等其他shell支持最广泛的一种。Bash(再次是Bourne壳)是Bourne壳的壳替代品。 Bash是sh的超集。 Bash支持sh。 POSIX是一组定义POSIX兼容系统应如何工作的标准。 Bash实际上不是POSIX兼容的外壳。在脚本语言中,我们将解释器表示为
#!/bin/bash
。类比:
Shell就像接口,规范或API。
sh是实现Shell接口的类。
bash是sh的子类。
评论
我不明白您已经提到“ Bash是sh的超集”和“ Bash是sh的子类”,这不是相反的陈述吗?你能澄清一下吗?
– Keerthana Prabhakaran
18年4月26日在6:13
我认为这是要说Bash从sh继承(因此它是OOP的“子类”)并对其进行扩展(因此具有功能的超集)。
–tripleee
18年5月19日在4:44
#5 楼
来自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
上表的键。
Y可以使用此shell进行功能。
N功能部件不存在于外壳程序中。
F功能部件只能通过使用shells函数
机制来实现。
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
2015年9月12日在20:43
让我给出一些提示:在1989年Bourne Shell中添加了作业控制,并在2005年将Bourne Shell设置为OpenSource。Korn Shell至少从1988年开始具有流程替代,从1997年以来就是OpenSource。BTW:关于$ ENV的声明是不正确的,$ ENV仅针对交互式外壳程序被读取/执行。
–schily
2015年9月12日于20:47
@schily此帖是从cs.virginia.edu/helpnet/Computer_OS/unix/shells/shelldiff.html捕获的
–SriniV
2015年9月14日下午5:35
@schily如果您觉得它在任何地方都不正确,请随时对其进行适当的编辑。
–SriniV
2015年9月14日下午5:36
根据揭露的内容,似乎最好删除此答案,因为它本质上是欺诈性的,OP并没有真正审查他粘贴的信息。
– danno
2015年10月17日,0:12
#6 楼
TERMINAL打开窗口的程序
xterm,rxvt,konsole,kvt,gnome-terminal,nxterm和eterm。
SHELL
是在终端上运行的程序
Shell既是命令解释器又是编程语言。
Shell只是执行命令的宏处理器。
宏处理器意味着可以扩展文本和符号以创建更大的表达式的功能。
SHvs。 BASH
SH
(SHell)
是特定的shell
命令解释器和编程语言
BASH
BASH
(Bourne-Again SHell)
是特定的shell
命令解释器和编程语言
具有sh功能和更多功能
SH的后继产品
BASH是默认的SHELL
参考材料:
SHELL
gnu.org:
Shell在其基础上只是执行
命令的宏处理器。宏处理器一词是指将文本和
符号扩展以创建更大的表达式的功能。
Unix 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是shell或命令语言解释器,用于GNU
操作系统。该名称是'Bourne-Again SHell'的首字母缩写,
是Stephen Bourne的双关语,Stephen Bourne是当前Unix shell sh的直接祖先的作者,出现在第七版的Bell Labs
研究版本的Unix。
Bash在很大程度上与sh兼容,并结合了Korn shell ksh和C shell csh的有用功能。它旨在作为IEEE POSIX规范(IEEE标准1003.1)的IEEE POSIX外壳和工具部分的
一致实现。它为交互式和编程使用提供了
sh上的功能改进。
虽然GNU操作系统提供了其他shell,包括csh的
版本,但Bash是默认外壳。像其他GNU软件一样,
Bash具有相当的可移植性。它目前可以在几乎所有版本的Unix和其他一些操作系统上运行-存在独立支持的端口,用于MS-DOS,OS / 2和Windows平台。
#7 楼
其他答案通常指出Bash与POSIX Shell标准之间的区别。但是,在编写可移植的shell脚本并使用Bash语法时,非常典型的bashism列表和相应的纯POSIX解决方案非常方便。当Ubuntu从Bash切换为Dash作为默认系统外壳时,已经编译了这样的列表,并且可以在这里找到:https://wiki.ubuntu.com/DashAsBinSh
此外,还有一个名为checkbashisms的强大工具,它可以检查脚本中的bashisms,并在您要确保脚本可移植时方便使用。
评论
基本上,这就是我到目前为止的答案。 +1
–tripleee
17年8月8日在8:46
#8 楼
它们几乎相同,但是bash
具有更多功能– sh
(或多或少)是bash
的较旧子集。 1977年。但是,实际上,最好将其视为与1992年的POSIX标准兼容的高度交叉兼容的外壳。以
sh
开头的脚本或通常使用Bourne shell
外壳的脚本这样做是为了向后兼容。任何unix / linux操作系统都将具有bash
外壳。在Ubuntu上,Bourne *again* shell
经常调用#!/bin/sh
,而在MacOS上,它是sh
的特殊POSIX版本。对于标准兼容的行为,速度或向后兼容性,可能首选这些shell。sh
比原始的sh
更新,添加了更多功能,并寻求与dash
向后兼容。从理论上讲,bash
程序应在bash
中运行。 sh
在几乎所有linux / unix机器上都可用,并且通常默认情况下使用-值得注意的是,MacOS在Catalina(10.15)之前默认为sh
。 FreeBSD默认情况下未安装sh
。评论
远远早于POSIX。这些天,您希望找到的所有sh至少与POSIX兼容;但是在旧系统上,这绝不是给定的。 POSIX的标准化远不止外壳。实际上,您可能会认为操作系统调用和库函数的标准化更为重要。
–tripleee
19/12/18在15:04
我删除了有关POSIX的内容,以减少混乱
–瑞安·泰勒(Ryan Taylor)
19/12/18在20:02
#9 楼
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。
#10 楼
/bin/sh
可能会或可能不会调用与/bin/bash
相同的程序。sh
至少支持POSIX所需的功能(假设实现正确)。它也可能支持扩展。bash
,“ Bourne Again Shell”,实现了sh以及bash特定的扩展所需的功能。完整的扩展程序集太长,无法在此处描述,并且随新版本的发布而变化。差异记录在bash手册中。键入info bash
并阅读“ Bash功能”部分(当前版本中的第6部分),或在线阅读当前文档。评论
如果您在当前shell中设置了正确的PATH,sh仅会为您提供POSIX shell。没有为您提供POSIX Shell的已定义PATH名称。
–schily
2015年9月12日在21:37
长期以来,例如在Solaris上,sh甚至不一定为您提供POSIX shell。
–tripleee
16年4月14日在4:19
#11 楼
尽可能地做到以下几点:有了基本的了解之后,上面发布的其他注释将更容易理解。
Shell-“ Shell”是一个程序,可以简化用户和操作系统(内核)之间的交互。有许多Shell实现可用,例如sh,bash,csh,zsh ...等。
使用任何Shell程序,我们将能够执行该Shell程序支持的命令。
Bash-它再次源自Bourne Shell。使用此程序,我们将能够执行Shell指定的所有命令。另外,我们将能够执行一些专门添加到该程序中的命令。 Bash与sh具有向后兼容性。
Sh-它来自Bourne Shell。 “ sh”支持外壳程序中指定的所有命令。就是说,使用该程序,我们将能够执行Shell指定的所有命令。
有关更多信息,请执行:
-https://man.cx/sh
-https://man.cx/bash
评论
要了解POSIX,请阅读Alex的回复,请检查:stackoverflow.com/a/1780614/1261003
–赖汉堡
4月16日晚上10:21
我不是想了解POSIX。我正在审核您的答案,因此,我需要查看它,您的答案会增加价值。我认为没有。
– Scratte
4月16日10:23
我相信这些小的澄清将有助于新手更轻松地理解以上讨论中使用的术语。 @Scratte
–赖汉堡
4月16日10:25
#12 楼
Linux操作系统提供了不同类型的Shell。尽管shell有许多共同的命令,但是每种类型都有其独特的功能。让我们研究一下最常用的shell。
Sh shell:
Sh shell也是被称为Bourne Shell。 Sh shell是1977年由AT&T的Bell Labs的Stephen Bourne为Unix计算机开发的第一个shell。它包含许多脚本工具。
Bash shell:
Bash shell代表Bourne再次壳牌。 Bash shell是大多数linux发行版中的默认shell,并替代Sh Shell(Sh shell也将在Bash shell中运行)。 Bash Shell可以执行绝大多数Sh Shell脚本,而无需进行修改,并且还提供命令行编辑功能。
评论
肯·汤普森(Ken Thompson)之前有一个炮弹。 Bourne shell在v7 Unix(1979)中正式引入。
–tripleee
19/12/18在15:26
评论
有关适用于Bourne shell的bashism的有用列表和相应代码,请参见mywiki.wooledge.org/Bashism您可能需要查看sh的POSIX标准及其命令语言:* sh * Shell命令语言
一般而言,由于所有pos脚本都具有posix兼容性,因此所有sh脚本都将在bash下运行,但并非所有bash脚本都可以在sh下运行,您注意到的主要区别是类似[[]]而不是[]比较,该比较允许未加引号的空格, $(())而不是$ []算术表达式,以及其他类似的东西,例如直接来自bash文档的“它太大而又太慢”。但是,新脚本编写者不必将自己限制在与sh兼容的脚本中,除非它们正在针对某些脚本进行射击向后兼容,这些天通常不是这种情况,毕竟是(或曾经是)2014年吧?