shell基础知识目录
一、指定执行脚本的shell
在脚本的开头指定执行该脚本的shell程序:
#!/bin/bash or #!/bin/sh or #!/bin/ksh
二、设置调试模式
在进行脚本调试时,可以对需要进行调试的语句设置调试输出模式。
sh和ksh选项 | ksh特有选项 | 说明 |
---|---|---|
set -x / set +x | set -o xtrace / set +o xtrace | 在解析通配符和变量之后输出语句 |
set -v / set + v | set -o verbose / set +o verbose | 在解析通配符和变量之前输出语句 |
set -f / set +f | set -o noglob / set +o noglob | 禁用文件名生成(使用通配符) |
#使用-x让脚本在解析变量之后输出语句示例
set -x
a=2
b=`expr $a + 2`
echo $b
set +x
#执行脚本时输出结果:
+ a=2
++ expr 2 + 2
+ b=4
+ echo 4
4
+ set +x
# 使用set -v让脚本在解析变量之前输出语句示例
a=2
b=`expr $a + 2`
expr $a + 2
echo $b
4
set +v
三、注释
在shell中使用#注释单行,多行则可以用 :<<‘EOF’ 和 EOF配对来进行多行注释。
#!/bin/bash
#set -x
:<<'EOF'
a=2
b=`expr $a + 2`
echo $b
EOF
#set +x
四、变量
在Bourne Shell中,主要包含字符串(strings)和常量(constants)两种类型的变量。在Korn shell中,有四种类型的变量:字符串(strings),整数(integers),数组(arrays)和常量(constants)。
默认情况下,所有变量都是字符串类型,除非明确地指定了变量类型,在ksh中,使用typeset设置变量的类型。
#使用typeset定义整数变量
typeset -i num=1
echo $num
#1
num=5
echo $num
#5
num='char'
echo $num
#0
#使用integer定义整数变量
integer num2=5
echo $num2
#5
num2='strings'
echo $num
#0
在Bourne Shell中,使用readonly var[=value]来定义常量。在Korn Shell中,还可以使用typeset -r var[=value]来定义常量。
#使用readonly定义常量
readonly const1='alphabet'
const1='number'
ksh: const1: is read only
#使用typeset定义常量
typeset -r const2=100
const2=200
ksh: const2: is read only
五、通配符
通配符 | 说明 |
---|---|
? | 匹配单个字符 |
^ | 匹配行开头 |
$ | 匹配行尾 |
< | 匹配单词的开头 |
> | 匹配单词的结尾 |
[] | 匹配指定字符集中的任意字符 |
[-] | 匹配范围内任意字符 |
* | 匹配前面字符的0次或多次 |
. | 匹配任一个字符 |
[^] 或[!] | 匹配除了指定字符集的任意字符 |
\( \) | 正则表达式匹配组字符集 |
x{m} | 重复字符x为m次,如/[0-9]{8}/匹配包含8个数字的字符串 |
x{m,} | 重复字符x为至少m次,如/[0-9]{8,}/匹配包含至少8个数字的字符串 |
x{m,n} | 重复字符x为至少m次,不多于n次,如/[0-9]{8,10}/匹配包含至少8个数字最多10个数字的字符串 |
\ | 去除字符的特殊含义 |
‘’ | 去除单引号’'中包含的所有字符的特殊含义 |
“” | 去除双引号“”中包含的除了$,‘,“和\之外的其他字符的特殊含义 |
非打印字符的正则表达式通配符 | 说明 |
---|---|
\s | 匹配任何空白字符,包括空格、制表符、换页符等,等价于[ \f\n\r\t\v] |
\S | 匹配任何非空白字符,等价于[^ \f\n\r\t\v] |
\f | 匹配一个换页符 |
\n | 匹配一个换行符 |
\r | 匹配一个回车符 |
\t | 匹配一个制表符 |
\v | 匹配一个垂直制表符 |
ksh case模式通配符 | 说明 |
---|---|
?(pat1|pat2|…|patn) | 匹配0次或1次指定的模式 |
@(pat1|pat2|…|patn) | 匹配1次指定的模式 |
*(pat1|pat2|…|patn) | 匹配0次,1次或多次指定的模式 |
+(pat1|pat2|…|patn) | 匹配1次或多次指定的模式 |
!(pat1|pat2|…|patn) | 匹配指定模式外的任意模式 |
六、shell命令执行结果引用
在Bourne shell中使用``保存命令输出的结果,在Korn shell中还可以使用$(command)保存命令的输出结果。
day=`date +%D`
echo $day
#10/09/21
month=$(date +%m)
echo $month
#10
如果命令的输出为多行,则在引用保存命令输出的变量时要用双引号“"包含变量,否则输出变量时只显示为一行。
file=`cat /etc/fstab`
echo $file
# # /etc/fstab # Created by anaconda on Mon Sep 13 11:39:56 2021 # # Accessible filesystems, by reference, are maintained under '/dev/disk' # See man pages fstab(5), findfs(8), mount(8) and/or blkid(8) for more info # /dev/mapper/rhel-root / xfs defaults 0 0 UUID=722b5e8f-6da6-4eba-abfe-8c6e7fddd67b /boot xfs defaults 0 0 /dev/mapper/rhel-home /u01 xfs defaults 0 0 /dev/mapper/rhel-swap swap swap defaults 0 0 tmpfs /dev/shm tmpfs defaults,size=21G 0 0
echo "$file"
#
# /etc/fstab
# Created by anaconda on Mon Sep 13 11:39:56 2021
#
# Accessible filesystems, by reference, are maintained under '/dev/disk'
# See man pages fstab(5), findfs(8), mount(8) and/or blkid(8) for more info
#
/dev/mapper/rhel-root / xfs defaults 0 0
UUID=722b5e8f-6da6-4eba-abfe-8c6e7fddd67b /boot xfs defaults 0 0
/dev/mapper/rhel-home /u01 xfs defaults 0 0
/dev/mapper/rhel-swap swap swap defaults 0 0
tmpfs /dev/shm tmpfs defaults,size=21G 0 0
七、读取键盘或文件输入
当脚本在执行的时候需要读取键盘输入时,可以使用read语句将输入内容保存到相应的变量。当需要输入多个变量时,shell会使用IFS变量定义的分隔符(缺省是空格)来分隔输入内容,然后分别存放到各变量。如果分隔后的内容段数量多于变量的数量,则最后一个变量保存所有剩余的内容段。
read var1 var2 var3
#2021 10 09
echo $var1
#2021
echo $var2
#10
echo $var3
#09
echo -e "Enter your name:\c"
read name junk
echo -e "\n\tHello,$name"
# Hello,John
在ksh中,可以将提示输入的信息直接放到read语句中以简化脚本的编写。
#!/bin/ksh
read name?"Enter your name:"
echo -e "\n\tHello,$name"
可以通过以下方法从文件中读取内容保存到变量。
cat contact
# Harry,86802200,Shanghai
# Tom,26801308,Chengdu
# Lison,13084113,Beijing
# Omin,98121582,Guangzhou
#方法1
IFS=,
while read name number district
do
echo "Employee ${name}'s phone number is $number, who is located in ${district}."
done < contact
#方法2
IFS=,
cat contact |while read name number district
do
echo "Employee ${name}'s phone number is $number, who is located in ${district}."
done
#Employee Harry's phone number is 86802200, who is located in Shanghai.
#Employee Tom's phone number is 26801308, who is located in Chengdu.
#Employee Lison's phone number is 13084113, who is located in Beijing.
#Employee Omin's phone number is 98121582, who is located in Guangzhou.
#对于只有一个变量的情况,还可以用以下方法3
for var in `cat $filename`
do
echo $var
done
八、shell特殊变量
shell特殊变量 | 说明 |
---|---|
$0 | 当前脚本的名称 |
$n(n≥1) | 传递给脚本或函数的参数。第一个参数是$1,第二个参数是$2… |
${10} | ksh中的第10个参数,对于Bourne shell,只有1-9个参数,在多于9个参数时使用shift将参数传递向左给$1 |
$# | 传递给脚本或函数的参数个数 |
$* | 传递给脚本或函数的所有参数 |
$@ | 传递给脚本或函数的所有参数,当被双引号”“包含时,$@与$*稍有不同。$@是一个字符串列表,$*是一个以IFS变量定义的分隔符分隔的长字符串。 |
$? | 上个命令的退出状态或函数的返回值 |
$$ | 当前shell的进程号。对于shell脚本,就是脚本所在的进程号 |
$! | 上一个运行的后台进程的进程号 |
#判断参数的数量
if [ $# -ne 2]
then
echo "USAGE: $0 arg1 arg2"
fi
#循环获取参数
cat test.sh
while [ $# -gt 0 ]
do
echo $1
echo "argument number: $#"
shift
done
./test.sh arg1 arg2 arg3 arg4 arg5 arg6 arg7 arg8 arg9 arg10 arg11
arg1
arg2
arg3
arg4
arg5
arg6
arg7
arg8
arg9
arg10
arg11
九、脚本命令短选项
短选项语法:getopts options [opt_args] var
为了处理命令行提供的无效选项,在单字符的选项前加上“:”,如:
while getopts :xy opt_char
加上“:”后在遇到无效的选项时会将opt_char设置为“?”,并将无效选项赋值给变量OPTARG。
USAGE="usage: $0 -n -t"
while getopts :nt opt_char
do
case $opt_char in
n)
echo "You entered the n option"
;;
t)
echo "You entered the t option"
;;
\?)
echo "$OPTARG is not a valid option."
echo "$USAGE"
;;
esac
done
# sh test.sh -s
s is not a valid option.
usage: test.sh -n -t
如果一个选项后必须要跟有参数,那么在这个选项后加上“:”,如:
while getopts :x :y opt_char
在x选项后加上“:”后,必须有参数跟在x选项后,同时参数会被赋值给OPTARG变量。
USAGE="usage: $0 [-d] [-m month]"
year=$(date +%Y)
while getopts :dm: opt_char
do
case $opt_char in
d)
echo -n "Date: " # -d option given
date
;;
m)
cal $OPTARG $year # -m option given with an arg
;;
\?)
echo "$OPTARG is not a valid option."
echo "$USAGE"
;;
:)
echo "The $OPTARG option requires an argument."
echo "$USAGE"
;;
esac
done
十、判断语句
在Bourne shell或Korn Shell中,使用[ … ]作为数字或字符串的比较,不过要注意在“[“的右边和”]“的左边加上空格。
在Korn Shell中,还可以使用[[ … ]]进行字符串的比较,((…))进行数字的比较。
1.判断文件类型
标记 | Bourne Shell | Korn Shell | 说明 |
---|---|---|---|
-f | [-f file ] | [[ -f fille ]] | 判断是否为普通文件 |
-d | [ -d file ] | [[ -d file ]] | 判断是否为目录 |
-c | [ -c file ] | [[ -c file ]] | 判断是否为raw设备 |
-b | [ -b file ] | [[ -b file ]] | 判断是否为块设备 |
-p | [ -p file ] | [[ -p file ]] | 判断是否为管道 |
-S | [ -S file ] | [[ -S file ]] | 判断是否为socket |
-L | [ -L file ] | [[ -L file ]] | 判断是否为符号链接 |
-e | [ -e file ] | [[ -e file ]] | 判断文件是否为存在 |
-s | [ -s file ] | [[ -s file ]] | 判断文件是否为存在且大小大于0 |
2.判断文件权限
标记 | Bourne Shell | Korn Shell | 说明 |
---|---|---|---|
-r | [-r file ] | [[ -r fille ]] | 判断用户对文件是否有可读权限 |
-w | [ -w file] | [[ -w file ]] | 判断用户对文件是否有可写权限 |
-x | [ -x file ] | [[ -x file ]] | 判断用户对文件是否有可执行权限 |
-O | [ -O file ] | [[ -O file ]] | 判断用户是否是文件的属主 |
-G | [ -G file ] | [[ -G file ]] | 判断文件的属组是否和用户的属组相同 |
-u | [ -u file ] | [[- u file ]] | 判断文件是否设置了set-user-ID |
-g | [ -g file ] | [[ -g file ]] | 判断文件是否设置了set-group-ID |
-k | [ -k file ] | [[ -k file ]] | 判断文件是否设置了sticky bit |
3.字符串比较
Bourne Shell | Korn Shell | 说明 |
---|---|---|
[ str1 = str2 ] | [[ str1 == str2 ]] | 判断字符串str1是否等于str2 |
[ str1 != str2 ] | [[ str1 != str2 ]] | 判断字符串str1是否不等于str2 |
NA | [[ str1 == pattern ]] | 判断字符串str1是否匹配pattern |
NA | [[ str1 != pattern ]] | 判断字符串str1是否不匹配pattern |
[ str1 < str2 ] | [[ str1 < str2 ]] | 判断字符串str1按字典顺序是否小于str2 |
[ str1 > str2 ] | [[ str1 > str2 ]] | 判断字符串str1按字典顺序是否大于str2 |
[ -z str1 ] | [[ -z str1 ]] | 判断字符串str1是否为空,注意在变量前后要加双引号 |
[ -n str1 ] | [[ -n str1 ]] | 判断字符串str1是否不为空,注意在变量前后要加双引号 |
if [ -z "$str1" ]
then
echo "str1 is null"
fi
3.数字比较
Bourne Shell | Korn Shell | 说明 |
---|---|---|
[ num1 -eq num2 ] | ((num1 == num2)) | 判断数字num1和num2是否相等 |
[ num1 -ne num2 ] | ((num1 != num2)) | 判断数字num1和num2是否不相等 |
[ num1 -lt num2 ] | ((num1 < num2)) | 判断数字num1是否小于num2 |
[ num1 -gt num2 ] | ((num1 > num2)) | 判断数字num1是否大于num2 |
[ num1 -le num2 ] | ((num1 <= num2)) | 判断数字num1是否小于或等于num2 |
[ num1 -ge num2 ] | ((num1 > =num2)) | 判断数字num1是否大于或等于num2 |
grep oracle /etc/passwd
if [ $? -eq 0 ]; then
echo " Found oracle! "
fi
4.判断字符串是否是数字
#判断变量是否为整数
echo $num | awk '{if($0~/^[0-9]*$/) print "integer number"}'
echo $num | awk '{print($0~/^[0-9]*$/)?"integer number":"string"}'
#判断是否是浮点数
echo $num |awk '{print($0~/^[-]?([0-9])+[.]?([0-9])+$/)?"float number":"string"}'
十一、数学运算
1.expr语句
expr语句将变量作为数字进行数学运算,注意在运算符和运算对象之间要用空格分开。
运算符 | 操作 | 示例 |
---|---|---|
+ | 加 | num2=`expr $num1 + 20` |
- | 减 | num3=`expr $num1 - $num2` |
* | 乘 | num3=`expr $num1 \* $num2` |
/ | 除 | num3=`expr $num1 / $num2` |
% | 求余 | num3=`expr $num1 % $num2` |
#使用\(和\)包含优先计算的数字,注意在\(后和\)前要加空格
echo `expr \( 3 + 2 \) \* 2`
2.ksh运算语句
运算符 | 操作 | 示例 | 结果 |
---|---|---|---|
+ | 加 | ((x = 54 + 25)) | 79 |
- | 减 | ((x = 80 - 22)) | 58 |
* | 乘 | ((x = 4 * 8)) | 32 |
/ | 除 | ((x = 24 / 4)) | 6 |
% | 求余 | ((x = 24 % 5)) | 4 |
# | 进制转换 | ((x = 2#1101010)) 或 ((x = 16#6A)) | 10#106 |
<< | 向左位移 | ((x = 2#11 << 3)) | 2#11000 |
>> | 向右位移 | ((x = 2#1001 >> 2)) | 2#10 |
& | 位与 | ((x = 2#101 & 2#110)) | 2#100 |
| | 位或 | ((x = 2#101 | 2#110)) | 2#111 |
^ | 异或 | ((x = 2#101 ^ 2#110)) | 2#11 |
3.let运算语句
let语句和ksh的运算语句((…))的作用一样,只能用于整数变量的运算。
let num3=num1+num2 #变量可加上
也
可
以
不
加
也可以不加
也可以不加
num1=15
num2=18
let num3=$num1+$num2 #let num3=num1+num2
echo $num3
33
4.浮点运算
可以使用bc进行浮点数运算。
x=51.9
y=98.6
z=`echo "scale=2;$x + $y" |bc`
echo $z
#150.5
5.布尔运算
运算符 | 操作 | Bourn Shell | Korn Shell |
---|---|---|---|
-a | 与 | if [ 表达式1 -a 表达式2 ] | if [[ 表达式1 && 表达式2 ]] |
-o | 或 | if [ 表达式1 -o 表达式2 ] | if [[ 表达式1 |
! | 或 | if [ ! 表达式1 ] | if [[ ! 表达式 ]] |
#判断年份是否为闰年sh脚本
#!/bin/sh
year=2021
if [ \( `expr $year % 400` -eq 0 \) -o \( \( `expr $year % 4` -eq 0 \) -a \( `expr $year % 100` -ne 0 \) \) ]
then
echo "$year is a leap year!"
else
echo "$year is not a leap year!"
fi
#判断年份是否为闰年ksh脚本
#!/bin/ksh
year=2020
if (( (($year % 400)) == 0 )) || (( (($year % 4)) == 0 && (((($year % 100)) != 0)) ))
then
echo "$year is a leap year!"
else
echo "$year is not a leap year!"
fi
#判断月份含有天数sh脚本
#!/bin/sh
month=`date +%m`
if [ "$month" -eq 2 ]
then
echo "Feburary has 28 days, otherwise it has 29 days when the year is a leap year."
elif [ \( "$month" -eq 4 \) -o \( "$month" -eq 6 \) -o \
\( "$month" -eq 9 \) -o \( "$month" -eq 11 \) ]
then
echo "The current month has 30 days."
else
echo "The current month has 31 days."
fi
#判断月份含有天数ksh脚本
#!/bin/ksh
month=$(date +%m)
if (("$month" == 2))
then
echo "Feburary has 28 days, otherwise it has 29 days when the year is a leap year."
elif [[ "$month" = @(4|6|9|11) ]]
then
echo "The current month has 30 days."
else
echo "The current month has 31 days."
fi
十二、条件判断语句
1.if语句
if [判断条件]
then
执行代码块
fi
if [判断条件]; then
执行代码块
fi
if [判断条件]
then
执行代码块1
else
执行代码块2
fi
if [判断条件1]
then
执行代码块1
elif [判断条件2]
执行代码块2
else
执行代码块3
fi
2.case语句
case $var in
值1)
执行代码块1
;;
值2)
执行代码块2
;;
*)
执行代码块3
;;
esac
#判断月份含有天数脚本
#!/bin/ksh
month=$(date +%m)
case "$month" in
02)
echo "Feburary has 28 days, otherwise it has 29 days when the year is a leap year."
;;
4|6|9|11)
echo "The current month has 30 days."
;;
*)
echo "The current month has 31 days."
;;
esac
十三、循环语句
1.for语句
for var in 参数列表
do
执行代码块1
done
#示例1
for disk in sdb sdc sdd sde sdf sdg
do
ls -l /dev/$disk
done
#示例2
for var in $*
do
echo "command line contains: $var"
done
#命令输出结果遍历示例
for pv in ` pvs|awk 'NR>=2 {print $1}'`
do
pvdisplay $pv
done
2.while语句
while [判断条件]
do
执行代码块
done
#示例
num=1
while [ $num -le 10 ]
do
echo $num
num=`expr $num + 1`
done
#示例2,当数字为0时条件判断为false
num=5
while (( num ))
do
echo $num
((num = num - 1))
done
3.until语句
until [判断条件]
do
执行代码块
done
#示例
num=1
until [ $num -gt 10 ]
do
echo $num
num=`expr $num + 1`
done
4.break语句
在满足某个特定的条件时,可以使用break跳出循环。
#!/bin/ksh
typeset -i num=0
while true
do
echo -n "Enter any number (0 to exit):"
read num junk
if (( num == 0 ))
then
break
else
echo "Square of $num is $(( num * num ))."
fi
done
5.select菜单
select var in 菜单选项列表
do
执行代码块
done
#!/bin/ksh
PS3="Enter the number for your fruit choice:"
select fruit in apple orange banana "Quit Menu"
do
case $fruit in
apple)
echo "An apple has 80 calories."
;;
orange)
echo "An orange has 65 calories."
;;
banana)
echo "A banana has 90 calories."
;;
"Quit Menu")
break
;;
*)
echo "Please try again. Use '1'-'3'"
;;
esac
done
十四、常用命令
1.grep命令
grep命令用于在文件或标准输入中查找符合指定样式的行。
常用选项 | 说明 |
---|---|
-c | 统计符合样式的行数 |
-E | 将样式作为正则表达式来使用 |
-i | 忽略大小写 |
-q | 不显示任何信息,一般用于脚本编写时根据前面命令执行的结果$?进行判断时使用 |
-v | 显示不符合样式的所有行 |
-w | 只显示全字符合的行 |
#示例
grep '^asm' /etc/group
asmadmin:x:504:grid
asmdba:x:506:grid,oracle
asmoper:x:507:grid
grep 'grid$' /etc/group
dba:x:502:oracle,grid
asmadmin:x:504:grid
asmoper:x:507:grid
grep 5 /etc/group
tty:x:5:
man:x:15:
ftp:x:50:
lock:x:54:
utempter:x:35:
libstoragemgmt:x:995:
nfsnobody:x:65534:
named:x:25:
radvd:x:75:
tss:x:59:
geoclue:x:985:
stapusr:x:156:
stapsys:x:157:
stapdev:x:158:
oinstall:x:501:
dba:x:502:oracle,grid
asmadmin:x:504:grid
asmdba:x:506:grid,oracle
asmoper:x:507:grid
grep -w 5 /etc/group
tty:x:5:
grep '\<5\>' /etc/group
tty:x:5:
2.cut命令
cut命令用于从文件或标准输入中截取特定的列或域。
常用选项 | 说明 |
---|---|
-c | 截取指定的字符数量 |
-f | 截取指定的域数 |
-d | 指定与空格不同的域分隔符 |
#以:为分隔符截取文件的第1个域
cut -d: -f1 /etc/group
#截取第1-8个字符
who -u |cut -c1-8
3.sort命令
sort命令用于对文件或标准输入的行进行排序。
常用选项 | 说明 |
---|---|
-b | 忽略每行前面开始的空格字符 |
-n | 依照数值的大小排序 |
-u | 去除重复的行 |
-r | 以倒序排列行 |
-o | 将排序后的结果存入指定的文件 |
-t | 排序时所有列的分隔符,如cut命令的-d参数或awk的-F参数 |
-k pos | 使用第几列的内容进行排序 |
sort -n -t: -k 3 /etc/passwd
root:x:0:0:root:/root:/bin/bash
bin:x:1:1:bin:/bin:/sbin/nologin
daemon:x:2:2:daemon:/sbin:/sbin/nologin
adm:x:3:4:adm:/var/adm:/sbin/nologin
lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin
sync:x:5:0:sync:/sbin:/bin/sync
shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown
4.tr命令
tr命令可以对标准输入的字符进行替换、压缩和删除,可以将一组字符变成另一组字符。
命令语法:
tr [OPTION]… SET1 [SET2]
SET1 指定要被转换或删除的原字符集
SET2 指定要转换成的目标字符集
常用选项 | 说明 |
---|---|
-c | 取数据流SET1指定字符的补集 |
-d | 删除SET1中指定的字符 |
-s | 将数据流SET1中连续的重复的字符用单个字符替代,如可以使用-s '\n’删除空行 |
#将小写字符转换成大写字符
echo "hello world" | tr 'a-z' 'A-Z'
HELLO WORLD
#删除指定的字符
echo "1 hello 2 world" | tr -d '0-9'
hello world
#删除指定字符的补集
echo "1 export 2 input 3 ps" |tr -d -c 'a-z \n'
# export input ps
5.tee命令
tee将命令结果同时输出到屏幕和文件。
echo "`date '+%F %H:%M:%S'` The script is running...." |tee -a /tmp/log
2021-10-15 18:33:59 The script is running....
cat /tmp/log
2021-10-15 18:33:59 The script is running....
6.find命令
find命令搜索符合某种条件的文件,然后将输出文件的路径和名称,也可以对文件进行统计,更改或删除等操作。
常用选项 | 说明 |
---|---|
-name | 查找匹配文件名 |
-user | 查找属于某个用户的文件 |
-atime | 查找上次访问时间是多少天之前的文件 |
-mtime | 查找上次修改时间是多少天之前的文件 |
-size | 查找占用多少空间的文件 |
操作选项 | 说明 |
---|---|
默认选项,查找到符合条件的文件后打印出来显示在屏幕上 | |
-exec | 对符合条件的文件执行命令 |
-ok | 对符合条件的每个文件在执行命令前都需要交互输入y才会执行相应的命令 |
#查找以.log结尾的文件
find /var/log -name "*.log" -print
#查找大于100M以上的文件
find / -size +100M -print
#删除上次修改时间大于90天以上的文件
find /backup -mtime +90 -exec rm -f {} \;
十五、命令重定向
标准输入输出 | 说明 |
---|---|
stdin(标准输入) | 默认是键盘,文件描述符为0 |
stdout(标准输出) | 默认是屏幕,文件描述符为1 |
stderr(标准错误) | 默认是屏幕,文件描述符为2 |
文件描述符3到9可以自定义分配给脚本要读取或输出的文件。
重定向命令 | 说明 |
---|---|
< file | 使用文件作为标准输入 |
0< file | 使用文件作为标准输入 |
> file | 将输出重定向到文件 |
1> file | 将输出重定向到文件 |
2> file | 将错误重定向到文件 |
exec fd> file | 将文件描述符fd分配给文件file作为输出使用,注意在文件描述符和>之间不含空格 |
exec fd<file | 将文件描述符fd分配给文件file作为输入使用,注意在文件描述符和<之间不含空格 |
read <&fd var1 | 从文件描述符fd中读入内容保存到变量var1中 |
cmd >& fd | 执行命令后将输出发送到文件 |
exec fd<&- | 关闭文件描述符 |
#use file /etc/hosts.old as input and /etc/hosts.new as output
#assign fd 3 to /etc/hosts.old, fd 4 to /etc/hosts.new
exec 3< /etc/hosts.old
exec 4> /etc/hosts.new
#
read <& 3 addr1 name1
read <& 3 addr2 name2
echo $name1 $addr1 >& 4
echo $name2 $addr2 >& 4
exec 3<&-
exec 4<&-
#将脚本执行的输出和错误信息都输出到script.out文件
script.sh > script.out 2>&1
还可以从标准输入获取数据,用于输出到屏幕或文件。方法如下:
cmd > file <<EOF
输入内容
EOF
echo "Select a fruit type?"
cat << EOF
apple
orange
grape
persimmon
EOF
echo -n "Which would you prefer? "
read fruitchoice
echo "Your fruit choice is ${fruitchoice}."
十六、函数
可以使用两种方式来定义函数,一种是使用Bourne shell的函数格式:
function_name ()
{
函数包含的语句
}
另一种是Korn shell的函数格式:
function function_name
{
函数包含的语句
}
示例:
f1 ()
{
echo "Bourne shell function"
}
f1
Bourne shell function
function f2
{
echo "Korn shell function"
}
f2
Korn shell function
函数可以使用return返回0到255之间的任意数值,缺省情况下,使用$?获取函数返回的值。
使用typeset -f function_name 可以查看函数的定义, unset -f function_name取消函数的定义。