命令格式:type 参数命令功能:判断一个命令是内置命令还是外部命令选项:-t:输出“file”、“alias”或者“builtin”,分别表示给定的指令为“外部指令”、“命令别名”或者“内部指令”;
-p:如果给出的指令为外部指令,则显示其绝对路径;
-a:在环境变量“PATH”指定的路径中,显示给定指令的信息,包括命令别名。实例:# type ls
ls 是 `ls --color=auto' 的别名
# type -t ls
alias
# type -a ls
ls 是 `ls --color=auto' 的别名
ls 是 /bin/ls
可以看出,ls为命令别名# type cd
cd 是 shell 内嵌
# type -t cd
builtin
# type -a cd
cd 是 shell 内嵌
可以看出,cd为内部命令# type which
which 是 /usr/bin/which
# type -t which
file
# type -p which
/usr/bin/which
# type -a which
which 是 /usr/bin/which
which 是 /bin/which
可以看出,which为外部命令通过,type 命令的用法,我们可以知道每个命令是否为 bash 内置命令。此外,使用 type 搜索后面的名称时,如果后接的名称不能以执行文件的状态找到,那么该名称不会显示。
2、echo
命令格式:echo arg功能:在屏幕上显示出有 arg 指定的字符串实例:简单显示:
# echo hello
hello创建shell脚本:
gedit hello.sh
#!/bin/bash
echo "hello world!"
执行 ./hello.sh
bash: ./hello.sh: 权限不够
添加权限:chmod +x *.sh 或者 chmod 777 *.sh
# ./hello.sh
hello world!扩展部分:echo命令 选项: -e:激活转义字符。 使用-e选项时,若字符串中出现以下字符,则特别加以处理,而不会将它当成一般文字输出:a 发出警告声;
删除前一个字符;
c 最后不加上换行符号;
f 换行但光标仍旧停留在原来的位置;
换行且光标移至行首;
光标移至行首,但不换行;
插入tab; v 与f相同;
\ 插入字符;
nn 插入nnn(八进制)所代表的ASCII字符;实例:# echo -e "e[1;31mThis is red texte[0m"
This is red text
# echo -e "e[1;42mGreed Backgrounde[0m"
Greed Background
通过重定向符“<”将命令的标准输入重新定位到指定文件中。一般形式:命令 < 文件名实例:查看脚本
# cat sh.sh
echo “you working directory is $(pwd)”
echo "the time is $(date)"
shell命令解析程序从脚本程序 sh.sh 中读取命令行并加以执行
# bash < sh.sh
“you working directory is /home/tarena/project/c_test”
the time is Wed Mar 22 10:07:45 CST 2017
2、管道
在 Linux 下我们可以采用管道操作符 “|”来连接多个命令或进程,在连接的管道线两边,每个命令执行时都是一个独立的进程。前一个命令的输出正是下一个命令的输入。这些进程可以同时进行,而且随着数据流在它们之间的传递可以自动地进行协调,从而能够完成较为复杂的任务。管道我们也并不陌生,之前讲 xargs 用法时有用到的。参看:C语言再学习 -- Xargs用法详解一般形式:[命令1] | [命令2] | [命令3]实例:ls 命令查看
# ls
sh.sh text.txt
可以可以指定查找脚本文件
# ls | grep *sh
sh.sh
条件测试有两种常用形式:第一种是用 test 命令与系统运算符一起使用,第二种是用一对方括号与系统运算符一起使用。这两种形式是完全等价的。注意,利用一对方括号表示条件测试时,左方括号“[”之后、右方括号“]”之前各应有一个空格。在大多数系统中,两者没有太大的区别,都使得程序设计语法看起来更加简单明了。实例:#!/bin/bash
#if test -f "$1"
if [ -f "$1" ]
then echo "$1 is an ordinary file."
else echo "$1 is not ordinary file."
fi
执行脚本:# ./sh.sh hello.txt
hello.txt is not ordinary file.
shell 编程中的 test 与 [] 命令 常见用法:参看:test 命令判断表达式:if test #表达式为真
if test ! #表达式为假
test 表达式1 –a 表达式2 #两个表达式都为真
test 表达式1 –o 表达式2 #两个表达式有一个为真
test 表达式1 ! 表达式2 #条件求反
判断字符串:test –n 字符串 #字符串的长度非零
test –z 字符串 #字符串的长度是否为零
test 字符串1=字符串2 #字符串是否相等,若相等返回true
test 字符串1!=字符串2 #字符串是否不等,若不等反悔false
判断整数:test 整数1 -eq 整数2 #整数相等
test 整数1 -ge 整数2 #整数1大于等于整数2
test 整数1 -gt 整数2 #整数1大于整数2
test 整数1 -le 整数2 #整数1小于等于整数2
test 整数1 -lt 整数2 #整数1小于整数2
test 整数1 -ne 整数2 #整数1不等于整数2
判断文件:test File1 –ef File2 两个文件是否为同一个文件,可用于硬连接。主要判断两个文件是否指向同一个inode。
test File1 –nt File2 判断文件1是否比文件2新
test File1 –ot File2 判断文件1比是否文件2旧
test –b file #文件是否块设备文件
test –c File #文件并且是字符设备文件
test –d File #文件并且是目录 test –e File #文件是否存在 (常用)
test –f File #文件是否为正规文件 (常用)
test –g File #文件是否是设置了组id
test –G File #文件属于的有效组ID
test –h File #文件是否是一个符号链接(同-L)
test –k File #文件是否设置了Sticky bit位
test –b File #文件存在并且是块设备文件
test –L File #文件是否是一个符号链接(同-h)
test –o File #文件的属于有效用户ID
test –p File #文件是一个命名管道
test –r File #文件是否可读
test –s File #文件是否是非空白文件
test –t FD #文件描述符是在一个终端打开的
test –u File #文件存在并且设置了它的set-user-id位
test –w File #文件是否存在并可写
test –x File #文件属否存在并可执行
功能:用于条件控制结构中语法格式1:if [条件判断表达式]; then
当条件表达式成立时,可以执行命令 fi语法格式2:if [条件判断表达式]; then
当条件表达式成立时,可以执行命令 else
当条件表达式不成立时,可以执行命令 fi语法格式3:if [条件判断表达式1]; then
当条件表达式1成立时,可以执行命令
elfi [条件判断表达式2]; then
当条件表达式2成立时,可以执行命令 else
当条件表达式1与2均不成立时,可执行命令 fi实例:#!/bin/bash
#if test -f "$1"
if [ -f "$1" ]
then echo "$1 is an ordinary file."
else echo "$1 is not ordinary file."
fi
执行脚本:# ./sh.sh hello.txt
hello.txt is not ordinary file.
case语句
功能:允许进行多重条件选择语法结构:case $变量名称 in
第一个变量内容)
程序段 (满足第一个变量内容)
;;
第二个变量内容)
程序段二(满足第二个变量内容)
;;
...
*)
程序段(均不满足前面的条件下)
...
;;
esac语法分析: 该语句执行过程是用“字符串”的值依次与各模式字符串进行比较,如果发现同某个匹配,那么就执行该模式字符串之后的各个命令,直至遇到两个分号为止;如果没有任何模式字符串与该字符串的值相符合,则不执行任何命令。在使用 case 语句时我们应该注意以下几点: 每个模式字符串后面可有一条或多条命令,它的最后一条命令必须以两个分号(即;;)结束。 模式字符串中可以使用通配符。 如果一个模式字符串中包含多个模式,那么各模式之间应以竖线(|)隔开,表示各模式是“或”的关系,即只要给定字符串与其中一个模式相配,就会执行其后的命令表。 各模式字符串应是唯一的,不应重复出现,因为“*”可以与任何字符串匹配,它如果第一个出现,就不会再检查其他模式了。 case 语句以关键字 case 开头,以关键字 esac (是 case 倒过来写)结束。 case 的退出(返回)值是整个结构中最后执行的那个命令的退出值;如果没有执行任何命令,那么退出值为零。实例:#!/bin/bash
echo "a) choice a"
echo "b) choice b"
echo "c) choice c"
echo -e "Please enter your choice:c"
read menu_choice
case "$menu_choice" in
a) echo "you choice a" ;;
b) echo "you choice b" ;;
c) echo "you choice c" ;;
*) echo "sorry, choice not exist" ;;
esac
执行脚本# ./sh.sh
a) choice a
b) choice b
c) choice c
Please enter your choice:a
you choice a
(3)循环结构
循环可以不断执行某个程序段,直到用户设置的条件实现为止。下面介绍几种常用的循环结构:
while do done 语句
语法结构:while [条件判断表达式]
do
程序段
done语法分析:当条件判断表达式成立时,就进行循环,直到条件判断表达式不成立才停止。实例:#!/bin/bash
echo "a) choice a"
echo "b) choice b"
echo "c) choice c"
echo -e "Please enter your choice:c"
read menu_choice
while [ "$menu_choice" != "a" ] && [ "$menu_choice" != "b" ] && [ "$menu_choice" != "c" ]
do
echo -e "Please enter your choice (a/b/c) to stop this programe:c"
read menu_choice
done
执行脚本# ./sh.sh
a) choice a
b) choice b
c) choice c
Please enter your choice:d
Please enter your choice (a/b/c) to stop this programe:a
until do done 语句
语法结构:until [条件判断表达式]
do
程序段
done语法分析:与前面的 while do done 刚好相反,它说的是“当条件判断表达式成立时,就终止循环,否则就持续执行循环的程序段”实例:#!/bin/bash
echo "a) choice a"
echo "b) choice b"
echo "c) choice c"
echo -e "Please enter your choice:c"
read menu_choice
until [ "$menu_choice" = "a" ] || [ "$menu_choice" = "b" ] || [ "$menu_choice" = "c" ]
do
echo -e "Please enter your choice (a/b/c) to stop this programe:c"
read menu_choice
done
执行脚本:# ./sh.sh
a) choice a
b) choice b
c) choice c
Please enter your choice:d
Please enter your choice (a/b/c) to stop this programe:a
for do done 语句
语句结构:for [条件判断表达式]
do
程序段
done语法分析:for 语句是最常用的建立循环结构的语句,其条件判断表达式更是形式多样,同 while 一样,是当满足条件判断时,就进行循环,知道条件不成立才停止。实例:#!/bin/bash
for num in 1 2 3 4 5
do
echo "$num"
done
执行脚本:# ./sh.sh
1
2
3
4
5
(4)其他结构:break 命令 和 continue 命令
break 命令
功能:可以使我们从循环体重退出来语法格式:break [ n ]
命令中 n 表示要跳出几层循环,默认值是 1,表示只跳出一层循环
continue 命令
功能:跳出循环体在它之后的语句,回到本层循环的开头,进行下次循环。语法格式:continue [ n ]
命令中 n 表示从包含 continue 语句的最内层循环体向外跳到第几层循环,默认值为 1,循环层数由内向外编号。
3、函数
到目前为止所编写的 shell 程序都是非常短小的。在实际应用中,有时为项目所编写的脚本程序时非常大型的,这时我们该如何构造自己的代码呢?可能想到说讲大型脚本按照功能模块拆分成多个小型脚本,但这种做法存在如下几个缺点. 在一个脚本程序中运行另外一个脚本程序要比执行一个函数慢得多。 返回执行结果变得更加困难,而且可能存在非常多的小脚本。基于上面原因及拆分思想,我们可以定义并使用 shell 函数语法格式:[function]函数名()
{
命令表 (statements)
}语法分析:关键字 function 可以默认。通常,函数中的最后一个命令执行之后,就退出被调用函数。我们也可以利用 return 命令立即退出函数语法格式:return [ n ]
命令中,n 值是退出函数时的退出值(退出状态),即 $? 的值。当 n 值缺省时,退出值是最后一个命令执行结果。函数应先定义,后使用。调用函数时,我们可以直接利用函数名,如 foo 不必带圆括号,就像一般命令那样使用。使用函数的最大作用就是可以简化很多代码,这在较大的 shell 脚本设计中国可能会更加明显。 实例:#!/bin/bash
first ()
{
echo "*****************************"
}
second ()
{
echo "============================="
}
trird ()
{
echo -e "fhello world!f"
}
first
second
trird
second
first
执行脚本:# ./sh.sh
*****************************
=============================
hello world!
=============================
*****************************
六、实例展示
#!/bin/sh
e=""
m=""
n="xxxx"
while [ 1 ]
do
n="xxxx"
e=`fdisk -l | grep /dev/sdb1 | awk '{print $1}'`
if [ -z "$e" ];then
echo "####no sd ####"
else
echo "####have sd !####"
m=`df | grep media | awk '{print $1}'`
if [ -n "$m" ];then
umount $m
fi
#umount $e
echo "####start to format sd with ext3 filesystem!####"
mkfs.ext3 "$e"
echo "####end format sd!####"
#echo "copy zslf_app_dir"
mount $e /media/mmcblk0p1
mkdir /media/mmcblk0p1/bak
mkdir /media/mmcblk0p1/video
mkdir /media/mmcblk0p1/video/temp
umount $e
echo "please remove sd!"
fi
sleep 5
if [ -n "$e" ];then
while [ -n "$n" ]
do
n=`fdisk -l | grep /dev/sdb1 | awk '{print $1}'`
sleep 5
done
fi
done #!/bin/sh
php_config_copy ()
{
echo "start copy the config file from jyzc to thttpd/www."
cp /jyzc/config/encodeCfg.xml /jyzc/thttpd-php/www/config/encodeCfg.xml
cp /jyzc/config/devInfo.txt /jyzc/thttpd-php/www/config/devInfo.txt
cp /etc/network/interfaces /jyzc/thttpd-php/www/config/interfaces
}
ppp_config_copy
{
echo "start copy th config file from jyzc/config to /etc/ppp/peers."
cp /jyzc/config/ppp-off /etc/ppp/peers/
cp /jyzc/config/ppp0_on_state.txt /etc/ppp/peers/
}
echo "############## jyzc ##################"
php_config_copy
ppp_config_copy
route del default
mknod /dev/pio c 203 0
cd /etc/ppp/information/
rm -rf addr.txt
echo " " > /etc/ppp/information/state.txt
#mknod -m 660 /dev/ttyUSB0 c 188 0
#mknod -m 660 /dev/ttyUSB1 c 188 1
#mknod -m 660 /dev/ttyUSB2 c 188 2
#mknod -m 660 /dev