Shell
介绍
1. 是一个命令解析器,为用户提供了一个向Linux内核发送请求以便运行程序的界面系统级程序
2. 由 C 语言编写
3. 既是一种命令语言,又是一种程序设计语言
4. 文件后缀 .sh(Unix、Linux、MacOS)
模型
┌────────────────────────────┐
│ File System / Application │
│ ┌──────────────────────┐ │
│ │ Shell │ │
│ │ ┌────────────────┐ │ │
│ │ │ Kernel │ │ │
│ │ │ ┌──────────┐ │ │ │
│ │ │ │ Hardware │ │ │ │
│ │ │ └──────────┘ │ │ │
│ │ └────────────────┘ │ │
│ └──────────────────────┘ │
└────────────────────────────┘
文件基本属性
drwxr-xr-x 2 username staff 64B 8 18 14:58 params
drwxr-xr-x 4 username staff 128B 8 18 14:58 symbol
-r-xr-xr-x 1 username staff 245B 8 18 15:03 params.sh
┬└┬┘└┬┘└┬┘ ┬ ────┬─── ──┬── ──┬─ ────┬───── ─┬─────────
│ │ │ │ │ │ │ │ │ └→ filename
│ │ │ │ │ │ │ │ └→ month/date/time last modified
│ │ │ │ │ │ │ └→ size
│ │ │ │ │ │ └→ group name
│ │ │ │ │ └→ user (owner) name
│ │ │ │ └→ number of hard links
│ │ │ └→ other (everyone) permissions
│ │ └→ group permissions
│ └→ user permissions
└→ file type (d: directory; -: file; l: link file;)
r w x
┬ ┬ ┬
│ │ └→ executable -> 1 (001)
│ └→ writeable -> 2 (010)
└→ readable -> 4 (100)
r-- = 4
r-x = 5
rwx = 7
chmod 755 test.sh
环境(解析器)
Bourne Shell(/usr/bin/sh 或 /bin/sh)
Bourne Again Shell(/bin/bash)
C Shell(/usr/bin/csh)
K Shell(/usr/bin/ksh)
Shell for Root(/sbin/sh)
Z-shell(/bin/zsh)
cat /etc/shells
/bin/bash
/bin/csh
/bin/dash
/bin/ksh
/bin/sh
/bin/tcsh
/bin/zsh
echo $0
source ~/.bash_profile
source ~/.zshrc
.sh 文件指定解析器
文件第一行加入
#!/bin/zsh
Hello World
echo 'Hello World!'
cat stdin.txt
特殊符号
使用变量($)
val=123
echo $val
unset val
注释( # )
单引号( '' )
echo 'val = $val'
双引号( "" )
echo "val = $val"
转译( \ )
echo "\"Hello World\!\""
连字符( {} )
echo ${val}${val}aa
标准输出 stdout( > , >> )
echo 'Hello World!' > stdout.txt
echo 'Hello World!' >> stdout.txt
标准输入 stdin( < )
grep 'l' < stdin.txt
参数传递
参数处理 |
说明 |
$# |
传递到脚本的参数个数 |
$* |
以一个单字符串显示所有向脚本传递的参数。如"$*"用「"」括起来的情况、以"$1 $2 … $n"的形式输出所有参数。 |
$$ |
脚本运行的当前进程ID号 |
$! |
后台运行的最后一个进程的ID号 |
$? |
获得之前(上一个)进程结束的状态码 (0 表示成功, 1 表示失败) |
$@ |
与$*相同,但是使用时加引号,并在引号中返回每个参数。如"$@"用「"」括起来的情况、以"$1" "$2" … "$n" 的形式输出所有参数。 |
$- |
显示Shell使用的当前选项,与set命令功能相同。 |
$_ |
表示的是打印上一个输入参数行, 当这个命令在开头时, 打印输出文档的绝对路径名. |
chmod 755 ./params.sh
./params.sh 1 2 3
#!/bin/zsh
echo "执行的文件名:$0";
echo "参数个数:$#";
echo "第一个参数为:$1";
echo "第二个参数为:$2";
echo "第三个参数为:$3";
echo "后台运行的最后一个进程的ID号:$!";
echo "进程ID号:$$";
运算符
算数运算符
运算符 |
说明 |
举例 |
+ |
加法 |
`expr $a + $b` 结果为 30。 |
- |
减法 |
`expr $a - $b` 结果为 -10。 |
* |
乘法 |
`expr $a \* $b` 结果为 200。 |
/ |
除法 |
`expr $b / $a` 结果为 2。 |
% |
取余 |
`expr $b % $a` 结果为 0。 |
= |
赋值 |
a=$b 把变量 b 的值赋给 a。 |
= ,== |
相等。用于比较两个数字,相同则返回 true。 |
[ $a = $b ] 或者 (( a == b )) 返回 false。 |
!= |
不相等。用于比较两个数字,不相同则返回 true。 |
[ $a != $b ] 返回 true。 |
a=10
b=20
val=`expr $a + $b`
echo "a + b : $val"
val=`expr $a - $b`
echo "a - b : $val"
val=`expr $a \* $b`
echo "a * b : $val"
val=`expr $b / $a`
echo "b / a : $val"
val=`expr $b % $a`
echo "b % a : $val"
if [ $a = $b ]
then
echo "a 等于 b"
fi
if [ $a != $b ]
then
echo "a 不等于 b"
fi
echo "a : $a"
echo "b : $b"
关系运算符
运算符 |
说明 |
举例 |
-eq |
检测两个数是否相等,相等返回 true。 |
[ $a -eq $b ] 返回 false。 |
-ne |
检测两个数是否不相等,不相等返回 true。 |
[ $a -ne $b ] 返回 true。 |
-gt |
检测左边的数是否大于右边的,如果是,则返回 true。 |
[ $a -gt $b ] 返回 false。 |
-lt |
检测左边的数是否小于右边的,如果是,则返回 true。 |
[ $a -lt $b ] 返回 true。 |
-ge |
检测左边的数是否大于等于右边的,如果是,则返回 true。 |
[ $a -ge $b ] 返回 false。 |
-le |
检测左边的数是否小于等于右边的,如果是,则返回 true。 |
[ $a -le $b ] 返回 true。 |
a=10
b=20
if [ $a -eq $b ]
then
echo "$a -eq $b : a 等于 b"
else
echo "$a -eq $b: a 不等于 b"
fi
if [ $a -ne $b ]
then
echo "$a -ne $b: a 不等于 b"
else
echo "$a -ne $b : a 等于 b"
fi
if [ $a -gt $b ]
then
echo "$a -gt $b: a 大于 b"
else
echo "$a -gt $b: a 不大于 b"
fi
if [ $a -lt $b ]
then
echo "$a -lt $b: a 小于 b"
else
echo "$a -lt $b: a 不小于 b"
fi
if [ $a -ge $b ]
then
echo "$a -ge $b: a 大于或等于 b"
else
echo "$a -ge $b: a 小于 b"
fi
if [ $a -le $b ]
then
echo "$a -le $b: a 小于或等于 b"
else
echo "$a -le $b: a 大于 b"
fi
布尔运算符
运算符 |
说明 |
举例 |
! |
非运算,表达式为 true 则返回 false,否则返回 true。 |
[ ! false ] 返回 true。 |
-o |
或运算,有一个表达式为 true 则返回 true。 |
[ $a -lt 20 -o $b -gt 100 ] 返回 true。 |
-a |
与运算,两个表达式都为 true 才返回 true。 |
[ $a -lt 20 -a $b -gt 100 ] 返回 false。 |
a=10
b=20
if [ ! $a = $b ]
then
echo "$a != $b : a 不等于 b"
else
echo "$a == $b: a 等于 b"
fi
if [ $a -lt 100 -a $b -gt 15 ]
then
echo "$a 小于 100 且 $b 大于 15 : 返回 true"
else
echo "$a 小于 100 且 $b 大于 15 : 返回 false"
fi
if [ $a -lt 100 -o $b -gt 100 ]
then
echo "$a 小于 100 或 $b 大于 100 : 返回 true"
else
echo "$a 小于 100 或 $b 大于 100 : 返回 false"
fi
if [ $a -lt 5 -o $b -gt 100 ]
then
echo "$a 小于 5 或 $b 大于 100 : 返回 true"
else
echo "$a 小于 5 或 $b 大于 100 : 返回 false"
fi
逻辑运算符
运算符 |
说明 |
举例 |
&& |
逻辑的 AND |
[[ $a -lt 100 && $b -gt 100 ]] 返回 false |
|| |
逻辑的 OR |
[[ $a -lt 100 || $b -gt 100 ]] 返回 true |
a=10
b=20
if [[ $a -lt 100 && $b -gt 100 ]]
then
echo "返回 true"
else
echo "返回 false"
fi
if [[ $a -lt 100 || $b -gt 100 ]]
then
echo "返回 true"
else
echo "返回 false"
fi
字符串运算符
运算符 |
说明 |
举例 |
= |
检测两个字符串是否相等,相等返回 true。 |
[ $a = $b ] 返回 false。 |
!= |
检测两个字符串是否不相等,不相等返回 true。 |
[ $a != $b ] 返回 true。 |
-z |
检测字符串长度是否为0,为0返回 true。 |
[ -z $a ] 返回 false。 |
-n |
检测字符串长度是否不为 0,不为 0 返回 true。 |
[ -n "$a" ] 返回 true。 |
$ |
检测字符串是否不为空,不为空返回 true。 |
[ $a ] 返回 true。 |
a="abc"
b="efg"
if [ $a = $b ]
then
echo "$a = $b : a 等于 b"
else
echo "$a = $b: a 不等于 b"
fi
if [ $a != $b ]
then
echo "$a != $b : a 不等于 b"
else
echo "$a != $b: a 等于 b"
fi
if [ -z $a ]
then
echo "-z $a : 字符串长度为 0"
else
echo "-z $a : 字符串长度不为 0"
fi
if [ -n "$a" ]
then
echo "-n $a : 字符串长度不为 0"
else
echo "-n $a : 字符串长度为 0"
fi
if [ $a ]
then
echo "$a : 字符串不为空"
else
echo "$a : 字符串为空"
fi
文件测试运算符
运算符 |
说明 |
举例 |
-b file |
检测文件是否是块设备文件,如果是,则返回 true。 |
[ -b $file ] 返回 false。 |
-c file |
检测文件是否是字符设备文件,如果是,则返回 true。 |
[ -c $file ] 返回 false。 |
-d file |
检测文件是否是目录,如果是,则返回 true。 |
[ -d $file ] 返回 false。 |
-f file |
检测文件是否是普通文件(既不是目录,也不是设备文件),如果是,则返回 true。 |
[ -f $file ] 返回 true。 |
-g file |
检测文件是否设置了 SGID 位,如果是,则返回 true。 |
[ -g $file ] 返回 false。 |
-k file |
检测文件是否设置了粘着位(Sticky Bit),如果是,则返回 true。 |
[ -k $file ] 返回 false。 |
-p file |
检测文件是否是有名管道,如果是,则返回 true。 |
[ -p $file ] 返回 false。 |
-u file |
检测文件是否设置了 SUID 位,如果是,则返回 true。 |
[ -u $file ] 返回 false。 |
-r file |
检测文件是否可读,如果是,则返回 true。 |
[ -r $file ] 返回 true。 |
-w file |
检测文件是否可写,如果是,则返回 true。 |
[ -w $file ] 返回 true。 |
-x file |
检测文件是否可执行,如果是,则返回 true。 |
[ -x $file ] 返回 true。 |
-s file |
检测文件是否为空(文件大小是否大于0),不为空返回 true。 |
[ -s $file ] 返回 true。 |
-e file |
检测文件(包括目录)是否存在,如果是,则返回 true。 |
[ -e $file ] 返回 true。 |
file="./arithmetic.sh"
if [ -r $file ]
then
echo "文件可读"
else
echo "文件不可读"
fi
if [ -w $file ]
then
echo "文件可写"
else
echo "文件不可写"
fi
if [ -x $file ]
then
echo "文件可执行"
else
echo "文件不可执行"
fi
if [ -f $file ]
then
echo "文件为普通文件"
else
echo "文件为特殊文件"
fi
if [ -d $file ]
then
echo "文件是个目录"
else
echo "文件不是个目录"
fi
if [ -s $file ]
then
echo "文件不为空"
else
echo "文件为空"
fi
if [ -e $file ]
then
echo "文件存在"
else
echo "文件不存在"
fi
test 命令
数值测试
参数 |
说明 |
-eq |
等于则为真 |
-ne |
不等于则为真 |
-gt |
大于则为真 |
-ge |
大于等于则为真 |
-lt |
小于则为真 |
-le |
小于等于则为真 |
num1=100
num2=100
if test $[num1] -eq $[num2]
then
echo '两个数相等!'
else
echo '两个数不相等!'
fi
字符串测试
参数 |
说明 |
= |
等于则为真 |
!= |
不相等则为真 |
-z |
字符串 字符串的长度为零则为真 |
-n |
字符串 字符串的长度不为零则为真 |
num1="abc"
num2="a1bc"
if test $num1 = $num2
then
echo '两个字符串相等!'
else
echo '两个字符串不相等!'
fi
文件测试
参数 |
说明 |
-e 文件名 |
如果文件存在则为真 |
-r 文件名 |
如果文件存在且可读则为真 |
-w 文件名 |
如果文件存在且可写则为真 |
-x 文件名 |
如果文件存在且可执行则为真 |
-s 文件名 |
如果文件存在且至少有一个字符则为真 |
-d 文件名 |
如果文件存在且为目录则为真 |
-f 文件名 |
如果文件存在且为普通文件则为真 |
-c 文件名 |
如果文件存在且为字符型特殊文件则为真 |
-b 文件名 |
如果文件存在且为块特殊文件则为真 |
if test -e ./noFile
then
echo '文件已存在!'
else
echo '文件不存在!'
fi
流程控制
if else
if condition
then
command1
command2
...
commandN
fi
if condition
then
command1
command2
...
commandN
else
command
fi
if condition1
then
command1
elif condition2
then
command2
else
commandN
fi
for 循环
for var in item1 item2 ... itemN
do
command1
command2
...
commandN
done
for loop in 1 2 3 4 5
do
echo "The value is: $loop"
done
for str in This is a string
do
echo $str
done
while 语句
while condition
do
command
done
i=1
sum=0
while ((i <= 100))
do
((sum += i))
((i++))
done
echo "The sum is: $sum"
无限循环
while :
do
command
done
while true
do
command
done
for (( ; ; ))
until 循环
until condition
do
command
done
a=0
until [ ! $a -lt 10 ]
do
echo $a
a=`expr $a + 1`
done
case ... esac
case 值 in
模式1)
command1
command2
...
commandN
;;
模式2)
command1
command2
...
commandN
;;
esac
num=2
case $num in
1) echo "num is 1"
;;
2|3) echo "num is $num"
;;
4) echo "num is 4"
;;
esac
跳出循环 break continue
#!/bin/zsh
while :
do
echo -n "输入 1 到 5 之间的数字,输入 q 结束循环,其他输入跳过该次循环:"
read aNum
case $aNum in
1|2|3|4|5) echo "你输入的数字为 $aNum!"
;;
q) echo "结束循环"
break
;;
*) echo "跳过该次循环"
continue
;;
esac
done
函数
[ function ] funname [()]
{
action;
[return int;]
}
demoFun(){
echo "这是我的第一个 shell 函数!"
}
demoFun
函数参数
参照 - 【参数传递】
#!/bin/zsh
funWithParam(){
echo "第一个参数为 $1 !"
echo "第二个参数为 $2 !"
echo "第十个参数为 $10 !"
echo "第十个参数为 ${10} !"
echo "第十一个参数为 ${11} !"
echo "参数总数有 $# 个!"
}
funWithParam 1 2 3 4 5 6 7 8 9 10 11
一些操作
查找指定目录下所有指定后缀的文件
read_dir(){
for file in `ls -a $1`
do
if [ -d $1"/"$file ]
then
if [[ $file != '.' && $file != '..' ]]
then
read_dir $1"/"$file $2 $3
fi
else
if [ "${file##*.}" = $2 ]
then
$3 $1"/"$file
fi
fi
done
}
callback(){
echo " -> $1"
}
read_dir . txt callback
通常可以使用find
命令查找指定文件
find . -name "*.txt"
find ./_trash -name params.sh
read_dir(){
for file in `find $1 -name "*.$2"`
do
$3 $file
done
}
callback(){
echo " -> $1"
}
read_dir . txt callback
连接远程服务器
如不支持ssh
命令,需安装Zlib
openSSL
openSSH
服务端需启动sshd
服务,需要开发相关端口22端口
21 → ftp
22 → ssh
23 → telnet
25 → smtp 邮件发送服务
ssh <USERNAME>@<IP> [-p <PORT>]
远程拷贝文件
scp [-r] file_source file_target
<USERNAME>@<IP>:<ABSOLUTE PATH>
scp ./shell.md root@<IP>:/root/
scp root@<IP>:/root/shell.md ./ssh/
修改文件内容
sed -i [-e <script>] [-f <script文件>] [文本文件]
sed -i -e "s/Hello/Hi/g" ./sed.txt
read_dir(){
for file in `find $1 -name "*.$2"`
do
$3 $file
done
}
callback(){
sed -i -e "s/Hi/Hello/g" $1
}
read_dir . txt callback