shell基础教程
Bash
简介Shell
的含义Shell
的种类命令行环境终端模拟器命令提示符进入和退出方法Shell
和Bash
的历史基本语法echo
命令-n
参数-e
参数命令格式空格分号命令的组合符&&
和||type
命令快捷键
Bash
简介
Bash
是Unix
系统和Linux
系统的一种Shell
(命令行环境),是目前绝大多数Linux
发行版的默认Shell
Shell
的含义
学习Bash
,首先需要理解Shell
是什么,Shell
这个单词的原意是“外壳”,跟kernel
(内核)相对应,比喻内核外面的一层,即用户跟内核交互的对话界面
具体来说,Shell
这个词有多种含义
首先,Shell
是一个程序,提供一个与用户对话的环境。这个环境只有一个命令提示符,让用户从键盘输入命令,所以又称为命令行环境(command line interface
,简写为CLI
)。Shell
接收到用户输入的命令,将命令送入操作系统执行,并将结果返回给用户。
其次,Shell
是一个命令解释器,解释用户输入的命令,它支持变量、条件判断、循环操作等语法,所以用户可以用Shell
命令写出各种小程序,又称为脚本(script
)。这些脚本都通过Shell
的解释执行,而不通过编译
最后,Shell
是一个工具箱,提供了各种小工具,供用户方便地使用操作系统地功能
Shell
的种类
Shell
有很多种,只要能给用户提供命令行环境的程序,都可以看作是Shell
。
历史上,主要是Shell
有下面这些
Bourne Shell(sh)
Bourne Again shell (bash)
C Shell (csh)
TENEX C Shell (tcsh)
Korn shell (ksh)
Z Shell (zsh)
Friendly Interactive Shell (fish)
Bash
是目前最常用的Shell
,除非特别指明,下文的Shell
的Bash
当作同义词使用,可以互换
下面的命令可以查看当前运行的Shell
$ echo $SHELL
/bin/bash
下面的命令可以查看当前的Linux
系统安装所有的Shell
$ cat /etc/shells
上面两个命令中,$
是命令行环境的提示符,用户只需要输入提示符后面的内容
Linux
允许每个用户使用不同的Shell
,用户的默认Shell
,或者与Bash
兼容
命令行环境
终端模拟器
如果是不带有图形环境的 Linux
系统(比如专用于服务器的系统),启动后就直接是命令行环境。
不过,现在大部分的 Linux
发行版,尤其是针对普通用户的发行版,都是图形环境。用户登录系统后,自动进入图形环境,需要自己启动终端模拟器,才能进入命令行环境。
所谓“终端模拟器”(terminal emulator
)就是一个模拟命令行窗口的程序,让用户在一个窗口中使用命令行环境,并且提供各种附加功能,比如调整颜色、字体大小、行距等等。
不同 Linux
发行版(准确地说是不同的桌面环境)带有的终端程序是不一样的,比如 KDE
桌面环境的终端程序是 konsole
,Gnome
桌面环境的终端程序是 gnome-terminal
,用户也可以安装第三方的终端程序。所有终端程序,尽管名字不同,基本功能都是一样的,就是让用户可以进入命令行环境,使用 Shell
。
命令提示符
进入命令行环境以后,用户会看到 Shell
的提示符。提示符往往是一串前缀,最后以一个美元符号$
结尾,用户可以在这个符号后面输入各种命令。
[user@hostname] $
上面例子中,完整的提示符是[user@hostname] $
,其中前缀是用户名(user
)加上@
,再加主机名(hostname
)。比如,用户名是bill
,主机名是home-machine
,前缀就是bill@home-machine
。
注意,根用户(root)的提示符,不以美元符号($
)结尾,而以井号(#
)结尾,用来提醒用户,现在具有根权限,可以执行各种操作,务必小心,不要出现误操作。这个符号是可以自己定义的,详见《命令提示符》一章。
为了简洁,后文的命令行提示符都只使用$
表示。
进入和退出方法
进入命令行环境以后,一般就已经打开 Bash
了。如果你的 Shell
不是 Bash
,可以输入bash
命令启动 Bash
。
$ bash
退出 Bash 环境,可以使用exit
命令,也可以同时按下Ctrl + d
。
$ exit
Bash 的基本用法就是在命令行输入各种命令,非常直观。作为练习,可以试着输入pwd
命令。按下回车键,就会显示当前所在的目录。
$ pwd
/home/me
如果不小心输入了pwe
,会返回一个提示,表示输入出错,没有对应的可执行程序。
$ pwe
bash: pwe:未找到命令
Shell
和Bash
的历史
Shell
伴随着 Unix
系统的诞生而诞生。
1969年,Ken Thompson
和 Dennis Ritchie
开发了第一版的 Unix
。
1971年,Ken Thompson
编写了最初的 Shell
,称为 Thompson shell
,程序名是sh
,方便用户使用 Unix
。
1973年至1975年间,John R. Mashey
扩展了最初的 Thompson shell
,添加了编程功能,使得 Shell
成为一种编程语言。这个版本的 Shell
称为 Mashey shell
。
1976年,Stephen Bourne
结合 Mashey shell
的功能,重写一个新的 Shell
,称为 Bourne shell
。
1978年,加州大学伯克利分校的 Bill Joy
开发了 C shell
,为 Shell
提供 C 语言的语法,程序名是csh
。它是第一个真正替代sh
的 UNIX shell
,被合并到 Berkeley UNIX
的 2BSD
版本中。
1979年,UNIX
第七版发布,内置了 Bourne Shell
,导致它成为 Unix
的默认 Shell
。注意,Thompson shell
、Mashey shell
和 Bourne shell
都是贝尔实验室的产品,程序名都是sh
。对于用户来说,它们是同一个东西,只是底层代码不同而已。
1983年,David Korn
开发了Korn shell
,程序名是ksh
。
1985年,Richard Stallman
成立了自由软件基金会(FSF
),由于 Shell
的版权属于贝尔公司,所以他决定写一个自由版权的、使用 GNU
许可证的 Shell
程序,避免 Unix
的版权争议。
1988年,自由软件基金会的第一个付薪程序员 Brian Fox
写了一个 Shell
,功能基本上是 Bourne shell
的克隆,叫做 Bourne-Again Shell
,简称 Bash
,程序名为bash
,任何人都可以免费使用。后来,它逐渐成为 Linux
系统的标准 Shell
。
1989年,Bash
发布1.0版。
1996年,Bash
发布2.0版。
2004年,Bash
发布3.0版。
2009年,Bash
发布4.0版。
2019年,Bash
发布5.0版。
用户可以通过bash
命令的--version
参数或者环境变量$BASH_VERSION
,查看本机的 Bash
版本。
$ bash --version
GNU bash,版本 5.0.3(1)-release (x86_64-pc-linux-gnu)
# 或者
$ echo $BASH_VERSION
5.0.3(1)-release
基本语法
echo
命令
由于后面的例子会大量用到echo命令,这里先介绍这个命令。echo命令的作用是在屏幕输出一行文本,可以将该命令的参数原样输出。
$ echo hello world
hello world
上面例子中,echo的参数是hello world,可以原样输出。如果想要输出的是多行文本,即包括换行符。这时就需要把多行文本放在引号里面。
$ echo "<HTML>
<HEAD>
<TITLE>Page Title</TITLE>
</HEAD>
<BODY>
Page body.
</BODY>
</HTML>"
上面例子中,echo可以原样输出多行文本。
-n
参数
默认情况下,echo
输出的文本末尾会有一个回车符,-n
参数可以取消末尾的回车符,使得下一个提示符紧跟在输出内容的后面
$ echo -n hello world
hello world$
上面例子中,world
后面直接就是下一行的提示符$
。
$ echo a;echo b
a
b
$ echo -n a;echo b
ab
上面例子中,-n
参数可以让两个echo
命令的输出连在一起,出现在同一行。
-e
参数
-e
参数会解释引号(双引号和单引号)里面的特殊字符(比如换行符\n
)。如果不使用-e
参数,即默认情况下,引号会让特殊字符变成普通字符,echo
不解释它们,原样输出。
$ echo "Hello\nWorld"
Hello\nWorld
# 双引号的情况
$ echo -e "Hello\nWorld"
Hello
World
# 单引号的情况
$ echo -e 'Hello\nWorld'
Hello
World
上面代码中,-e
参数使得\n
解释为换行符,导致输出内容里面出现换行。
命令格式
命令行环境中,主要通过使用 Shell 命令,进行各种操作。Shell 命令基本都是下面的格式。
$ command [ arg1 ... [ argN ]]
上面代码中,command
是具体的命令或者一个可执行文件,arg1 ... argN
是传递给命令的参数,它们是可选的。
$ ls -l
上面这个命令中,ls
是命令,-l
是参数。
有些参数是命令的配置项,这些配置项一般都以一个连词线开头,比如上面的-l
。同一个配置项往往有长和短两种形式,比如-l
是短形式,--list
是长形式,它们的作用完全相同。短形式便于手动输入,长形式一般用在脚本之中,可读性更好,利于解释自身的含义。
# 短形式
$ ls -r
# 长形式
$ ls --reverse
上面命令中,-r
是短形式,--reverse
是长形式,作用完全一样。前者便于输入,后者便于理解。
Bash 单个命令一般都是一行,用户按下回车键,就开始执行。有些命令比较长,写成多行会有利于阅读和编辑,这时可以在每一行的结尾加上反斜杠,Bash 就会将下一行跟当前行放在一起解释。
$ echo foo bar
# 等同于
$ echo foo \
bar
空格
Bash
使用空格(或 Tab
键)区分不同的参数。
$ command foo bar
上面命令中,foo
和bar
之间有一个空格,所以 Bash
认为它们是两个参数。
如果参数之间有多个空格,Bash
会自动忽略多余的空格。
$ echo this is a test
this is a test
上面命令中,a
和test
之间有多个空格,Bash 会忽略多余的空格。
分号
分号(;
)是命令的结束符,使得一行可以放置多个命令,上一个命令执行结束后,再执行第二个命令。
$ clear; ls
上面例子中,Bash 先执行clear
命令,执行完成后,再执行ls
命令。
注意,使用分号时,第二个命令总是接着第一个命令执行,不管第一个命令执行成功或失败。
命令的组合符&&
和||
除了分号,Bash 还提供两个命令组合符&&
和||
,允许更好地控制多个命令之间的继发关系。
Command1 && Command2
上面命令的意思是,如果Command1
命令运行成功,则继续运行Command2
命令。
Command1 || Command2
上面命令的意思是,如果Command1
命令运行失败,则继续运行Command2
命令。
下面是一些例子。
$ cat filelist.txt ; ls -l filelist.txt
上面例子中,只要cat
命令执行结束,不管成功或失败,都会继续执行ls
命令。
$ cat filelist.txt && ls -l filelist.txt
上面例子中,只有cat
命令执行成功,才会继续执行ls
命令。如果cat
执行失败(比如不存在文件flielist.txt
),那么ls
命令就不会执行。
$ mkdir foo || mkdir bar
上面例子中,只有mkdir foo
命令执行失败(比如foo
目录已经存在),才会继续执行mkdir bar
命令。如果mkdir foo
命令执行成功,就不会创建bar
目录了。
type
命令
Bash 本身内置了很多命令,同时也可以执行外部程序。怎么知道一个命令是内置命令,还是外部程序呢?
type
命令用来判断命令的来源。
$ type echo
echo is a shell builtin
$ type ls
ls is hashed (/bin/ls)
上面代码中,type
命令告诉我们,echo
是内部命令,ls
是外部程序(/bin/ls
)。
type
命令本身也是内置命令。
$ type type
type is a shell builtin
如果要查看一个命令的所有定义,可以使用type
命令的-a
参数。
$ type -a echo
echo is shell builtin
echo is /usr/bin/echo
echo is /bin/echo
上面代码表示,echo
命令既是内置命令,也有对应的外部程序。
type
命令的-t
参数,可以返回一个命令的类型:别名(alias
),关键词(keyword
),函数(function
),内置命令(builtin
)和文件(file
)。
$ type -t bash
file
$ type -t if
keyword
上面例子中,bash
是文件,if
是关键词。
快捷键
Bash 提供很多快捷键,可以大大方便操作。下面是一些最常用的快捷键,完整的介绍参见《行操作》一章。
Ctrl + L
:清除屏幕并将当前行移到页面顶部。Ctrl + C
:中止当前正在执行的命令。Shift + PageUp
:向上滚动。Shift + PageDown
:向下滚动。Ctrl + U
:从光标位置删除到行首。Ctrl + K
:从光标位置删除到行尾。Ctrl + D
:关闭 Shell 会话。↑
,↓
:浏览已执行命令的历史记录。
除了上面的快捷键,Bash 还具有自动补全功能。命令输入到一半的时候,可以按下 Tab 键,Bash 会自动完成剩下的部分。比如,输入pw
,然后按一下 Tab 键,Bash 会自动补上d
。
除了命令的自动补全,Bash 还支持路径的自动补全。有时,需要输入很长的路径,这时只需要输入前面的部分,然后按下 Tab 键,就会自动补全后面的部分。如果有多个可能的选择,按两次 Tab 键,Bash 会显示所有选项,让你选择。