基本格式
$ command [options] [arguments]
#!/bin/bashecho "Hello World !"
所谓 Shell 内建命令,就是由 Bash 自身提供的命令,而不是文件系统中的某个可执行文件。
例如,用于进入或者切换目录的 cd 命令,虽然我们一直在使用它,但如果不加以注意很难意识到它与普通命令的性质是不一样的:该命令并不是某个外部文件,只要在 Shell 中你就一定可以运行这个命令。
可以使用 type
来确定一个命令是否是内建命令:
$ type cdcd is a Shell builtin$ type ifconfigifconfig is /sbin/ifconfig
由此可见,cd
是一个 Shell 内建命令,而 ifconfig
是一个外部文件,它的位置是 /sbin/ifconfig
。
还记得系统变量 $PATH
吗?$PATH
变量包含的目录中几乎聚集了系统中绝大多数的可执行命令,它们都是外部命令。
通常来说,内建命令会比外部命令执行得更快,执行外部命令时不但会触发磁盘 I/O
,还需要 fork
出一个单独的进程来执行,执行完成后再退出。而执行内建命令相当于调用当前 Shell 进程的一个函数。
使用 alias
命令自定义别名的语法格式:
alias new_name='command'
比如,一般的关机命令 ``shutdown -h now` 写起来比较长,这时可以重新定义一个关机命令:
alias sd='shutdown -h now'
再如,通过 date
命令可以获得当前的 UNIX 时间戳,具体写法为 date +%s
:
alias timestamp='date +%s'
在代码中使用 alias
命令定义的别名只能在当前 Shell 进程中使用,在子进程和其它进程中都不能使用。当前 Shell 进程结束后,别名也随之消失。
用于在终端输出字符串,并在最后默认加上换行符。
#!/bin/bashname="tsejx"url="https://github.com/tsejx"# 直接输出字符串echo "Hello world!"# 输出变量echo $url# 双引号包围的字符串中可以解析变量echo "${name}的网址是:${url}"# 单引号包围的字符串不能解析变量echo '${name}的网址是:${url}'
用于标准输入中读取数据并赋值给变量。如果没有进行重定向,默认就是从键盘读取用户输入的数据;如果进行了重定向,那么可以从中读取数据。
read [-options] [variables]
options
表示选项variables
表示用来存储数据的变量,可以有一个,也可以有多个两个参数都是可选的,如果没有提供变量名,那么读取的数据将存放到环境变量 REPLY
中。
🌰 示例:
#!/bin/bashread -p "Enter some information > " name url ageecho "Website:$name"echo "Url: $url"echo "Age: $age"
注意,必须在一行内输入所有的值,不能换行,否则只能给第一个变量赋值,后续变量都会赋值失败。
示例:指定时间内输入密码
#!/bin/bashifread -t 20 -sp "Enter password in 20 seconds >" pass1 && printf "\n" && #第一次输入密码read -t 20 -sp "Enter password in 20 seconds> " pass2 && printf "\n" && #第二次输入密码thenecho "Valid password"elseecho "Invalid password"fi
这段代码中,我们使用 &&
组合了多个命令,这些命令会依次执行,并且从整体上作为 if
语句的判断条件,只要其中一个命令执行失败(退出状态为非 0 值),整个判断条件就失败了,后续的命令也就没有必要执行了。
退出当前 Shell 进程,并返回一个退出状态;使用$?可以接收这个退出状态。
exit
命令可以接受一个整数值作为参数,代表退出状态。如果不指定,默认状态值是 0。
exit
退出状态只能是一个介于 0~255 之间的整数,其中只有 0 表示成功,其它值都表示失败。
Shell 进程执行出错时,可以根据退出状态来判断具体出现了什么错误,比如打开一个文件时,我们可以指定 1 表示文件不存在,2 表示文件没有读取权限,3 表示文件类型不对。
#!/bin/bashecho "befor exit"exit 8echo "after exit"
只会打印出 berfore exit
,这说明遇到 exit
命令后,test.sh
执行就结束了。
⚠️ 注意,exit 表示退出当前 Shell 进程,我们必须在新进程中运行 test.sh,否则当前 Shell 会话(终端窗口)会被关闭,我们就无法看到输出结果了。
test
命令用于检测某个条件是否成立。
test expression
当 test
判断 expression
成立时,退出状态为 0,非欧泽为非 0 值。
test
命令也可以简写为 []
,它的用法为:
[expression]
文件类型判断
选项 | 作用 |
---|---|
-b filename | 判断文件是否存在,并且是否为块设备文件。 |
-c filename | 判断文件是否存在,并且是否为字符设备文件。 |
-d filename | 判断文件是否存在,并且是否为目录文件。 |
-e filename | 判断文件是否存在。 |
-f filename | 判断文件是否存在,井且是否为普通文件。 |
-L filename | 判断文件是否存在,并且是否为符号链接文件。 |
-p filename | 判断文件是否存在,并且是否为管道文件。 |
-s filename | 判断文件是否存在,并且是否为非空。 |
-S filename | 判断该文件是否存在,并且是否为套接字文件。 |
文件权限判断
选项 | 作用 |
---|---|
-r filename | 判断文件是否存在,并且是否拥有读权限。 |
-w filename | 判断文件是否存在,并且是否拥有写权限。 |
-x filename | 判断文件是否存在,并且是否拥有执行权限。 |
-u filename | 判断文件是否存在,并且是否拥有 SUID 权限。 |
-g filename | 判断文件是否存在,并且是否拥有 SGID 权限。 |
-k filename | 判断该文件是否存在,并且是否拥有 SBIT 权限。 |
文件比较
选项 | 作用 |
---|---|
filename1 -nt filename2 | 判断 filename1 的修改时间是否比 filename2 的新。 |
filename -ot filename2 | 判断 filename1 的修改时间是否比 filename2 的旧。 |
filename1 -ef filename2 | 判断 filename1 是否和 filename2 的 inode 号一致,可以理解为两个文件是否为同一个文件。这个判断用于判断硬链接是很好的方法 |
🌰 示例:
#!/bin/bashread filenameread urlif test -w $filename && test -n $urlthenecho $url > $filenameecho "写入成功"elseecho "写入失败"fi
选项 | 作用 |
---|---|
expression1 -a expression2 | 逻辑与,表达式 expression1 和 expression2 都成立,最终的结果才是成立的 |
expression1 -o expression2 | 逻辑或,表达式 expression1 和 expression2 有一个成立,最终的结果就成立。 |
!expression | 逻辑非,对 expression 进行取反。 |
🌰 示例:
#!/bin/bashread str1read str2#检测字符串是否为空if [ -z "$str1" -o -z "$str2" ] #使用 -o 选项取代之前的 ||thenecho "字符串不能为空"exit 0fi#比较字符串if [ $str1 = $str2 ]thenecho "两个字符串相等"elseecho "两个字符串不相等"fi