1.shell执行方式:
Shell脚本的执行方式可以有以下几种:
方式一: ./script.sh # 利用小数点来执行
方式二: sh script.sh或 bash script.sh # 利用bash(sh)来执行脚本
方式三: source script.sh # 利用source来执行
前面两种方式其实都是一样的:都是在当前父进程下的子进程中执行,子进程完成后,子进程中的各项变量或操作将会结束而不会传回到父进程中, 而通过第三种方式执行(source test.sh)的话,在父进程中执行的,进程执行完后,各项变量传回到父进程中.
2. test测试功能
2.1.关于某个档名的『文件类型』判断,如 test -e filename 表示存在否
-e 该『档名』是否存在?(常用)
-f 该『档名』是否存在且为档案(file)?(常用)
-d 该『文件名』是否存在且为目录(directory)?(常用)
-b 该『档名』是否存在且为一个block device 装置?
-c 该『档名』是否存在且为一个character device 装置?
-S 该『档名』是否存在且为一个Socket 档案?
-p 该『档名』是否存在且为一个FIFO (pipe) 档案?
-L 该『档名』是否存在且为一个连结档?
2.2 关于档案的权限侦测,如 test -r filename表示可读否(但 root 权限常有例外)
-r 侦测该档名是否存在且具有『可读』的权限?
-w 侦测该档名是否存在且具有『可写』的权限?
-x 侦测该档名是否存在且具有『可执行』的权限?
-u 侦测该文件名是否存在且具有『SUID』的属性?
-g 侦测该文件名是否存在且具有『SGID』的属性?
-k 侦测该文件名是否存在且具有『Sticky bit』的属性?
-s 侦测该档名是否存在且为『非空白档案』?
2.3 两个档案之间的比较,如: test file1 -nt file2
-nt (newer than)判断 file1 是否比 file2 新
-ot (older than)判断 file1 是否比 file2 旧
-ef 判断 file1 不 file2 是否为同一档案,可用在判断hard link 的判定上。主要意义在判定,两个档案是否均指向同一个 inode 哩!
2.4 关于两个整数之间的判定,例如 test n1 -eq n2
-eq 两数值相等 (equal)
-ne 两数值不等 (notequal)
-gt n1 大于 n2 (greater than)
-lt n1 小于 n2 (less than)
-ge n1 大于等于 n2 (greater than or equal)
-le n1 小于等于 n2 (less than or equal)
2.5 判定字符串的数据
test -z string 判定字符串是否为 0 ?若 string 为空字符串,则为 true
test -n string 判定字符串是否非为 0 ?若 string 为空字符串,则为false。
注: -n 亦可省略
test str1 = str2 判定 str1 是否等于str2 ,若相等,则回传 true
test str1 != str2 判定 str1 是否不等于str2 ,若相等,则回传false
2.6 多重条件判定,例如: test -r filename -a -xfilename
-a: (and)两状况同时成立!例如 test -rfile -a -x file,则 file 同时具有r 与 x 权限时,才回传 true。
-o :(or)两状况任何一个成立!例如 test -rfile -o -x file,则 file 具有 r或x 权限时,就可回传 true。
! :反相状态,如 test ! -x file,当 file 丌具有 x 时,回传 true
3.判断符号:[]
在中括号 [] 内的每个组件都需要有穸格键来分隑;
在中括号内的发数,最好都以双引号括号起来;
在中括号内的常数,最好都以单戒双引号括号起来。
[ "$HOME" == "$MAIL" ] 相当于 test $HOME = $MAIL
4.Shell script 的默认变数($0, $1...)
$# :代表执行脚本后接的参数『个数』
$@ :代表『"$1" "$2" "$3" "$4" 』之意,每个变量是独立的(用双引号括起来);
$* :代表『"$1c$2c$3c$4" 』,其中 c 为分隔字符,默讣为空格键,所以本例中代表『 "$1
$2 $3 $4" 』之意。
例子: 脚本:sh03.sh
#!/bin/bash
PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin
export PATH
echo "The script name is ==> $0"
echo "Total parameter number is ==>$#"
[ "$#" -lt 2 ] && echo"The number of parameter is less than 2. Stop here." && exit0
echo "Your whole parameter is ==>'$@'"
echo "The 1st parameter ==>$1"
echo "The 2nd parameter ==>$2"
执行: bash sh03.sh haha heihei hehe
执行结果:
The script name is ==> sh03.sh
Total parameter number is ==> 3
Your whole parameter is ==> ' haha heihei hehe '
The 1st parameter ==> haha
The 2nd parameter ==> heihei
5.条件判断式: if ... then
5.1单层、简单条件判断式:
if[ 条件判断式 ]; then
当条件判断式成立时,可以进行的指令工作内容;
fi<==将 if 反过来写,就成为 fi 啦!结束 if 之意!
如果是多条件时:
&&代表 AND ;
|| 代表 or ;
5.2 多重、复杂条件判断式
# 多个条件判断 (if ... elif... elif ... else) 分多种不同情况执行
if [ 条件判断式一 ]; then
当条件判断式一成立时,可以进行的指令工作内容;
elif [ 条件判断式二 ]; then
当条件判断式二成立时,可以进行的指令工作内容;
else
当条件判断式一与二均不成立时,可以进行的指令工作内容;
fi
6 条件判断式: case...esac
语法:
case $变量名称 in <==关键词为 case ,还有变量前有钱字号
"第一个变量内容") <==每个变量内容建议用双引号括起来,关键词则为小括号 )
程序段;; <==每个类别结尾使用两个连续的分号来处理!
"第二个变量内容")
程序段;;
*) <==最后一个变量内容都会用 * 来代表所有其他值,不包含第一个变量内容与第二个变量内容的其他程序执行段
exit1;;
esac <==最终的 case 结尾!『反过来写』思考一下!
7. function 功能
语法:
functionfname() {
程序段
}
那个 fname 就是我们的自定义的执行指令名称~而程序段就是我们要他执行的内容了。要注意的是,因为 shell script 的执行方式是由上而下,由左而右,因此在 shell script 当中的 function 的设定一定要在程序的最前面,这样才能够在执行时被找到可用的程序段喔!
例子:脚本:sh12.sh
#!/bin/bash
# Program:
# Use function to repeat information.
# History:
# 2005/08/29 VBird First release
PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin
export PATH
function printit(){
echo-n "Your choice is " # 加上 -n 可以丌断行继续在同一行显示
}
echo "This program will print yourselection !"
case $1 in
"one")
printit; echo $1 | tr 'a-z' 'A-Z' # 将参数做大小写转换!
;;
"two")
printit; echo $1 | tr 'a-z' 'A-Z'
;;
"three")
printit; echo $1 | tr 'a-z' 'A-Z'
;;
*)
echo "Usage $0 {one|two|three}"
;;
esac
8.循环
while do done, until do done (不定循环)
第一种: 当 condition 条件成立时,就进行循环,直到condition 的条件不成立才停止
while [ condition ] <==中括号内的状态就是刞断式
do <==do 是循环的开始!
程序段落
done <==done 是循环的结束
第二种: 当 condition 条件成立时,就终止循环,否则就持续进行循环的程序段。
until [ condition ]
do
程序段落
done
for...do...done (固定循环)
语法:
for var in con1 con2 con3 ...
do
程序段
done
举例: 脚本sh15.sh
#!/bin/bash
PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin
export PATH
for animal in dog cat elephant
do
echo"There are ${animal}s.... "
done
for...do...done 的数值处理:
语法:
for (( 初始值; 限制值; 执行步阶 ))
do
程序段
done
初始值:某个变量在循环当中的起始值,直接以类似 i=1 设定好;
限制值:当发量的值在这个限制值的范围内,就继续进行循环。例如 i<=100;
执行步阶:每作一次循环时,变量的变化量。例如 i=i+1。
举例: sh19.sh
#!/bin/bash
PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin
export PATH
read -p "Please input a number, I willcount for 1+2+...+your_input: " nu
s=0
for (( i=1; i<=$nu; i=i+1 ))
do
s=$(($s+$i))
done
echo "The result of '1+2+3+...+$nu' is==> $s"
9. shell script 的追踪与 debug
sh [-nvx] scripts.sh
选项与参数:
-n :不要执行 script,仅查询语法的问题;
-v :再执行 sccript 前,先将 scripts 的内容输出到屏幕上;
-x :将使用到的 script 内容显示到屏幕上,这是很有用的参数!
10.档案权限与目录配置
使用ls -al查看
第一栏代表这个档案的类型与权限(permission):
第一栏有十个字符:
第一个字符代表这个档案是『目录、档案或链接文件等等』
当为[ d ]则是目录,例如上表档名为『.gconf』的那一行;
当为[ - ]则是档案,例如上表档名为『install.log』那一行;
若是[ l ]则表示为连结档(link file);
若是[ b ]则表示为装置文件里面的可供储存的接口设备(可随机存取装置);
若是[ c ]则表示为装置文件里面的串行端口设备,例如键盘、鼠标
接下来的字符中,以三个为一组,且均为『rwx』的三个参数的组合。其中,[ r ]代表可读,(read)、[ w ]代表可写(write)、[ x ]代表可执行(execute)。要注意的是,这三个权限的位置不会改变,如果没有权限,就会出现减号[ - ]而已。
第一组为『档案拥有者的权限』
第二组为『同群组的权限』;
第三组为『其他非本群组的权限』。
第二栏表示有多少档名连结到此节点(i-node);
第三栏表示这个档案(或目录)的『拥有者账号』;
第四栏表示这个档案的所属群组;
第五栏为这个档案的容量大小,默认单位为 bytes;
第六栏为这个档案的建档日期或者是最近的修改日期;
第七栏为这个档案的档名
11.变量的设定
11.1变量的设定规则
1. 变量与变量内容以一个等号『=』来连结,如下所示:
『myname=VBird』
2. 等号两边不能直接接空格符,如下所示为错误:
『myname =VBird』或『myname=VBird Tsai』
3. 变量名称只能是英文字母与数字,但是开头字符不能是数字,如下为错误:
『2myname=VBird』
4.变量内容若有空格符可使用双引号『"』或单引号『'』将变量内容结合起来,但
o 双引号内的特殊字符如 $ 等,可以保有原本的特性,如下所示:
『var="lang is $LANG"』则『echo $var』可得『lang is en_US』
o 单引号内的特殊字符则仅为一般字符 (纯文本),如下所示:
『var='lang is $LANG'』则『echo $var』可得『lang is $LANG』
5. 可用跳脱字符『 \ 』将特殊符号(如 [Enter], $,\, 空格符, '等)变成一般字符;
6.在一串指令中,还需要藉由其他的指令提供的信息,可以使用反单引号『`指令`』或 『$(指
令)』。特别注意,那个 ` 是键盘上方的数字键 1 左边那个按键,而不是单引号! 例如想要取得核心版本的设定:
『version=$(uname -r)』再『echo $version』可得『2.6.18-128.el5』
7. 若该变量为扩增变量内容时,则可用"$变量名称" 或 ${变量} 累加内容,如下所示:
『PATH="$PATH":/home/bin』
8. 若该变量需要在其他子程序执行,则需要以export 来使变量变成环境变量:
『export PATH』
9. 通常大写字符为系统默认变量,自行设定变量可以使用小写字符,方便判断 (纯粹依照使用者兴趣与嗜好) ;
10. 取消变量的方法为使用 unset :『unset 变量名称』例如取消myname 的设定:
『unset myname』
11.2变量内容的删除与取代
12.3变量的测试与内容替换
12.重定向
大多数UNIX 系统命令从你的终端接受输入并将所产生的输出发送回到您的终端。一个命令通常从一个叫标准输入的地方读取输入,默认情况下,这恰好是你的终端。同样,一个命令通常将其输出写入到标准输出,默认情况下,这也是你的终端。
重定向命令列表如下:
命令 | 说明 |
command > file | 将输出重定向到 file。 |
command < file | 将输入重定向到 file。 |
command >> file | 将输出以追加的方式重定向到 file。 |
n > file | 将文件描述符为 n 的文件重定向到 file。 |
n >> file | 将文件描述符为 n 的文件以追加的方式重定向到 file。 |
n >& m | 将输出文件 m 和 n 合并。 |
n <& m | 将输入文件 m 和 n 合并。 |
<< tag | 将开始标记 tag 和结束标记 tag 之间的内容作为输入。 |
需要注意的是文件描述符 0 通常是标准输入(STDIN),1 是标准输出(STDOUT),2 是标准错误输出(STDERR)。
12.1输出重定向
重定向一般通过在命令间插入特定的符号来实现。特别的,这些符号的语法如下所示:
command1 > file1
上面这个命令执行command1然后将输出的内容存入file1。
注意任何file1内的已经存在的内容将被新内容替代。如果要将新内容添加在文件末尾,请使用>>操作符。
实例:
执行下面的 who 命令,它将命令的完整的输出重定向在用户文件中(users):
$ who > users
执行后,并没有在终端输出信息,这是因为输出已被从默认的标准输出设备(终端)重定向到指定的文件。
可以使用 cat 命令查看文件内容:
$ cat users
_mbsetupuser console Oct 31 17:35
tianqixin console Oct 31 17:35
tianqixin ttys000 Dec 1 11:33
输出重定向会覆盖文件内容,请看下面的例子:
$ echo "菜鸟教程:www.runoob.com" > users
$ cat users
菜鸟教程:www.runoob.com
$
如果不希望文件内容被覆盖,可以使用>>追加到文件末尾,例如:
$ echo "菜鸟教程:www.runoob.com" >> users
$ cat users
菜鸟教程:www.runoob.com
菜鸟教程:www.runoob.com
$
1> :以覆盖的方法将『正确的数据』输出到指定的档案或装置上;
1>>:以累加的方法将『正确的数据』输出到指定的档案或装置上;
2> :以覆盖的方法将『错误的数据』输出到指定的档案戒装置上;
2>>:以累加的方法将『错误的数据』输出到指定的档案戒装置上;
12.2输入重定向
和输出重定向一样,Unix 命令也可以从文件获取输入,语法为:
command1 < file1
这样,本来需要从键盘获取输入的命令会转移到文件读取内容。
注意:输出重定向是大于号(>),输入重定向是小于号(<)。
实例:
接着以上实例,我们需要统计 users 文件的行数,执行以下命令:
$ wc -l users
2 users
也可以将输入重定向到 users 文件:
$ wc -l < users
2
注意:上面两个例子的结果不同:第一个例子,会输出文件名;第二个不会,因为它仅仅知道从标准输入读取内容。
command1 < infile > outfile
同时替换输入和输出,执行command1,从文件infile读取内容,然后将输出写入到outfile中。
12.3重定向深入讲解
一般情况下,每个 Unix/Linux 命令运行时都会打开三个文件:
· 标准输入文件(stdin):stdin的文件描述符为0,Unix程序默认从stdin读取数据。
· 标准输出文件(stdout):stdout 的文件描述符为1,Unix程序默认向stdout输出数据。
· 标准错误文件(stderr):stderr的文件描述符为2,Unix程序会向stderr流中写入错误信息。
默认情况下,command > file 将 stdout 重定向到 file,command < file 将stdin 重定向到 file。
如果希望 stderr 重定向到 file,可以这样写:
$ command 2 > file
如果希望 stderr 追加到 file 文件末尾,可以这样写:
$ command 2 >> file
2 表示标准错误文件(stderr)。
如果希望将 stdout 和 stderr 合并后重定向到 file,可以这样写:
$ command > file 2>&1
或者
$ command >> file 2>&1
如果希望对 stdin 和 stdout 都重定向,可以这样写:
$ command < file1 >file2
command 命令将 stdin 重定向到 file1,将 stdout 重定向到 file2。
12.4HereDocument
HereDocument 是 Shell 中的一种特殊的重定向方式,用来将输入重定向到一个交互式 Shell 脚本或程序。
它的基本的形式如下:
command << delimiter
document
delimiter
它的作用是将两个 delimiter 之间的内容(document) 作为输入传递给 command。
注意:
· 结尾的delimiter一定要顶格写,前面不能有任何字符,后面也不能有任何字符,包括空格和 tab 缩进。
· 开始的delimiter前后的空格会被忽略掉。
实例
在命令行中通过 wc -l 命令计算 Here Document 的行数:
$ wc -l << EOF
欢迎来到
菜鸟教程
www.runoob.com
EOF
3 # 输出结果为 3 行
$
我们也可以将 Here Document 用在脚本中,例如:
#!/bin/bash
# author:菜鸟教程
# url:www.runoob.com
cat << EOF
欢迎来到
菜鸟教程
www.runoob.com
EOF
执行以上脚本,输出结果:
欢迎来到
菜鸟教程
www.runoob.com
/dev/null文件
如果希望执行某个命令,但又不希望在屏幕上显示输出结果,那么可以将输出重定向到 /dev/null:
$ command > /dev/null
/dev/null 是一个特殊的文件,写入到它的内容都会被丢弃;如果尝试从该文件读取内容,那么什么也读不到。但是 /dev/null 文件非常有用,将命令的输出重定向到它,会起到"禁止输出"的效果。
如果希望屏蔽 stdout 和 stderr,可以这样写:
$ command > /dev/null 2>&1
注意:0 是标准输入(STDIN),1 是标准输出(STDOUT),2 是标准错误输出(STDERR)。
13.管道
管道符号,是unix一个很强大的功能,符号为一条竖线:"|"。
用法: command 1 | command 2 他的功能是把第一个命令command 1执行的结果作为command 2的输入传给command 2,例如:
$ls -s|sort -nr (请注意不要复制$符号进去哦)
-s 是file size,-n是numeric-sort,-r是reverse,反转
该命令列出当前目录中的文档(含size),并把输出送给sort命令作为输入,sort命令按数字递减的顺序把ls的输出排序。
$ls -s|sort -n
按从小到大的顺序输出。
当然还可进行多次操作,如下面的功能为先去除纯数字,再由sed将竖线(这里不是管道符号)替换为空格,再将结果取出来排序,再进行结果的选择显示,不明白可查看 排序和分页。
cat filename |grep -v '^[0-9]*$' | sed 's/|/ /g' |sort -nrk 8 -nrk 9 |tail -n+1 |head -n 10