小白成长之路-Shell脚本
一·简介
shell脚本是很常用的工具,作为以后经常使用的“利器”,前面的基础知识要巩固,前期到语法之前的常用命令要知道,不然会影响以后的脚步编写。
二·前言
编程语言分类
静态和动态语言:
-
静态编译语言:使用变量前,先声明变量类型,之后类型不能改变,在编译时检查,如Java语言、C语言
-
动态编译语言:不事先声明,可随时改变类型,如Shell语言、python语言、javascript语言、php语言
强类型和弱类型语言:
-
强类型语言:不同类型数据操作,必须经过强制转换成同一类型才能运算,如java,C#
-
弱类型语言:语言的运行时会隐式地做数据类型转换。无需指定类型,默认均为字符型;参与计算会自动进行隐式类型转换;变量无需事先定义可直接调用。如Shell语言,php,JavaScript
脚本检查工具:
yum install -y epel-release
yum install -y ShellCheck
三·Shell脚本语言的基本结构
1·Shell脚本的用途:
-
自动化常用命令
-
执行系统管理和故障排除
-
创建简单的应用程序
-
处理文本或文件
2· Shell脚本基本结构:
Shell脚本编程:是基于过程式,解释执行的语言
编程语言的基本结构:
-
各种系统命令的组合
-
数据存储:变量,数组
-
表达式:a+b
-
控制语句:if、case、for、while
shell脚本:包含一些命令或声明,并符合一定格式的文本文件
格式要求:首行执行shebang机制
#声明后续语句是通过哪种语言写的
#!/bin/bash
#!/usr/bin/python
#!/usr/bin/perl
3· 创建Shell脚本过程
使用vim创建文本文件,第一行必须包括shell声明序列:
#!/bin/bash
加执行权限,给予执行权限,在命令行上指定脚本的绝对或相对路径
运行脚本,直接运行解释器,将脚本作为解释器程序的参数运行。
4· 脚本注释规范
-
第一行一般为调用使用的语言
-
程序名,避免更改文件名为无法找到正确的文件
-
版本号
-
更改后的时间
-
作者相关信息
-
该程序的作用,及注意事项
-
最后是各版本的更新简要说明
5·编写一个脚本
6·执行脚本
a.增加执行权限,执行脚本时会创建一个子shell,不影响现有的shell环境
chmod +x sh
./sh
/root/shellScript/sh
b.使用 . 或者source,执行脚本时不会创建一个子shell,会影响现有的shell环境
source sh
. sh#注意:尽量不要使用该方式执行脚本
7·脚本错误
-
语法错误,会导致后续的命令不继续执行,可以用bash -n shellname检查错误
-
命令错误,后续的命令还会继续,可以使用bash -x shellname检查
-
逻辑错误,只能使用bash -x进行观察
四·Shell脚本语言的变量用法详解
1·变量
变量表示命名的内存空间,将数据放在内存空间中,通过变量名引用,获取数据
2·变量类型
变量类型:
-
内置变量:如PS1,PATH,UID,HOSTNAME,HISTSIZE
-
用户自定义变量
-
预定义变量
-
位置变量
不同的变量存放的数据不同,决定了以下:
-
数据存储方式
-
参与的计算
-
表示的数据范围
变量数据类型:
-
字符串
-
数值:整型,浮点型(小数)、bash不支持浮点数
3· Shell中变量命名法则
-
不能使用程序中的保留字,如:if,for
-
只能使用数字,字母及下划线,且不能以数字开头
-
见名思意,用英文名字,并体现真正含义
-
统一命名规则:驼峰命名法
-
全局变量名大写
-
局部变量小写
-
函数名小写
4·变量定义和引用
变量的生效范围(变量作用域)
-
普通变量:生效范围为当前shell进程;对当前shell之外的其他shell进程,包括当前shell的子shell进程均无效
-
环境变量:生效范围为当前shell进程及其子进程
-
本地变量:生效范围为当前shell进程中某代码片段,通常指函数
变量赋值:
name="value"
value可以是以下多种类型
直接字符串:name='root'
变量引用:name="$USER"
命令应用:name=`command` || name=$(command)
通配符:FILE=/etc/* /*表示etc目录下所有的文件名*/##注意:变量赋值是临时生效,当退出终端后,变量会自动删除,无法持久保存。
变量引用:
$name
${name}
弱引用和强引用:
-
“$name”:弱引用,其中的变量引用会被替换成为变量值
-
‘$name’:强引用,其中的变量引用不会被替换成变量值,而保持原字符串
查看已定义的所有变量:
删除变量
5· 环境变量
环境变量:
-
可以使子进程(包括孙子进程)继承父进程的变量,但是无法让父进程使用子进程的变量。
-
一旦子进程修改了从父进程继承的变量,将会传递新的值给孙子进程
-
一般只在配置文件中使用,在脚本中较少使用
declare命令详解:
declare 为 shell 指令,在第一种语法中可用来声明变量并设置变量的属性([rix]即为变量的属性),在第二种语法中可用来显示 shell 函数。若不加上任何参数,则会显示全部的 shell 变量与函数(与执行 set 指令的效果相同)
declare [+/-][rxi][变量名称=设置值] 或 declare -f
参数说明:
-
+/- "-“可用来指定变量的属性,”+"则是取消变量所设的属性。
-
-f 仅显示函数
-
r 将变量声明为只读变量。注意,一旦设置为只读变量,既不能修改变量的值也不能删除变量,甚至不能通过+r取消只 读属性
-
x 指定的变量会成为环境变量,可供shell以外的程序来使用
-
i 将变量声明为整数型(integer)
-
p 显示指定变量的被声明类型。
6·只读变量
只读变量:只能声明定义,但后续不能修改和删除
声明只读变量:
readonly name
declare -r name
查看只读变量:
readonly [-p]
declare -r
7、位置变量
位置变量:在Bash Shell中内置的变量,在脚本代码中调用命令行传递给脚本的参数
符号 | 含义 |
$1,$2,. | 对应第一个,第二个等参数,shift[n]换位置,最多9个 |
$0 | 命令本身,包括路径 |
$* | 传递给脚本的所有参数,全部参数合成一个字符串 |
$@ | 传递给脚本的所有参数,每个参数为独立字符串 |
$# | 传递给脚本的参数的个数 |
$? | 上个命令的退出状态,或函数的返回值 |
$$ | 当前shell进程ID。对于Shell脚本,就是这些脚本所在的进程ID |
注意:$@,$*只有被双引号括起来的时候才会有差异
清空所有位置变量
set --
//写在脚本内部
8·退出状态码变量
进程执行后,将使用变量 ? 保存状态码的相关数字,不同的值反应成功与失败, ?保存状态码的相关数字,不同的值反应成功与失败, ?保存状态码的相关数字,不同的值反应成功与失败,的取值范围为[0,255]
$?的值为0 代表成功
$?的值不为0 代表失败(一般情况)
用户可以在脚本中使用以下命令自定义退出状态码
exit [n]
注意:
-
脚本中一旦遇到了exit命令,脚本会立即终止;终止退出状态取决于exit命令后面的数字
-
如果未给脚本指定退出状态码,整个脚本的退出状态码取决于脚本中执行的最后一条命令的状态码
exit
表示退出当前 Shell 进程,我们必须在新进程中运行 test.sh,否则当前 Shell 会话(终端窗口)会被关闭,我们就无法取得它的退出状态了
9·展开命令行
a.展开命令执行顺序
把命令行分成单个命令词
^
展开别名^
展开大括号的声明{}^
展开波浪符声明(~)^
命令替换$()和``
^
再次把命令行分成命令词
^
展开文件通配(*,?,[abc]等)
^
准备I/O重导向(<,>)
^
运行命令
b. 防止扩展
反斜线(\)会使随后的字符按原意解释
c.加引号来防止扩展
单引号(' ')防止所有扩展
双引号(" ")可防止扩展,但是以下清空例外:$(美元符号)
d.变量扩展
``:反引号,命令替换
\:反斜线,禁止单个字符扩展
!:叹号,历史命令替换
10·脚本安全和set
set命令:可以用来定制shell环境
a. $-变量
-
h:hashell,打开选项后,Shell会将命令所在的路径hash下来,避免每次都要查询。通过set +h将h选项关闭.默认开启
-
i:interactive-comments,包含这个选项说明当前的shell是一个交互式的shell。所谓的交互式shell,在脚本中,i选项是关闭的
-
m:monitor,打开监控模式,就可以通过Job control来控制进程的停止,继续,后台或者前台执行等
-
B:braccexpand,大括号扩展
-
H:history,H选项打开,可以展开历史列表中的命令,可以通过
!
来完成,例如!!
返回最近的一个历史命令,!n
返回第n个历史命令
b.set命令实现脚本安全
-
-u:在扩展一个没有设置的变量时,显示错误信息,等同于set -o nounset
-
-e:如果一个命令返回一个非0退出的状态值(失败)就退出,等同于set -o errexit
-
-o:option 显示,打开或关闭选项
-
显示选项:set -o
-
打开选项:set -o 选项
-
关闭选项:set +o 选项
-
-
-x:当执行命令时,打印命令及其参数,类似bash -x
五· Shell字符串详解
字符串(String)就是一系列字符的组合。字符串是Shell编程中最常用的数据类型之一
字符串可以由单引号''
包围,也可以由""
包围,也可以不用引号,三种方式的区别
-
由单引号
' '
包围的字符串-
任何字符都会原样输出,在其中使用变量是无效的
-
字符串中不能出现单引号,即使对单引号进行转义也不行
-
-
由双引号
" "
包围的字符串-
如果其中包含了某个变量,那么该变量就会被解析(得到该变量的值),而不是原样输出
-
字符串中可以出现双引号,只要进行转义就行
-
-
不被引号包围的字符串
-
不被引号包围的字符串中出现变量也会被解析,这一点和双引号
""
包围的字符串一样 -
字符串中不能出现空格,否则空格后面的字符串会作为其他变量或者命令解析
-
str1 中包含了$n
,它被解析为变量 n 的引用。$n
后边有空格,紧随空格的是 str2;Shell 将 str2 解释为一个新的变量名,而不是作为字符串 str1 的一部分
str2 中包含了引号,但是被转义了(由反斜杠\
开头的表示转义字符)。str2 中也包含了$n
,它也被解析为变量 n 的引用
str3 中也包含了$n
,但是仅仅是作为普通字符,并没有解析为变量 n 的引用
获取字符串长度
1·Shell字符串拼接
在脚本语言中,字符串的拼接(也称为字符串连接或者字符串合并)往往都非常简单,例如:
-
在
PHP
中使用.
即可连接两个字符串 -
在
JavaScript
中使用+
即可将两个字符串合并为一个
然而,在Shell中你不需要使用任何运算符,将两个字符串并排放在一起就能实现拼接
2·Shell字符串截取
Shell截取字符串通常有两种方式,从指定位置开始截取和从指定字符(子字符串)开始截取
从指定位置开始截取
这种方式需要两个参数:除了指定起始位置,还需要截取长度,才能最终确定要截取的字符串
既然需要指定起始位置,那么就要涉及到计数方向的问题,到底是从字符串左边开始计数,还是从字符串右边开始计数?答案是:Shell同时支持两种计数方式
格式 | 说明 |
---|---|
${string:start :length} | 从string字符串的左边第start个字符开始,向右截取length个字符。 |
${string:start} | 从string字符串的左边第start个字符开始截取,直到最后。 |
${string:0-start:length} | 从string字符串的右边第start个字符开始,向右截取length个字符。 |
${string:0-start} | 从string字符串的右边第start个字符开始截取,直到最后。 |
${string#*chars} | 从string字符串第一次出现chars的位置开始,截取chars右边的所有字符。 |
${string##*chars} | 从string字符串最后一次出现chars的位置开始,截取chars右边的所有字符。 |
${string%chars*} | 从string字符串第一次出现chars的位置开始,截取chars左边的所有字符。 |
${string%%chars*} | 从string字符串最后一次出现chars的位置开始,截取chars左边的所有字符。 |
4·Shell的格式化输出printf
a.语法格式:
printf "指定的格式" "文本1" "文本2" .....
b.常用格式替换符:
替换符 | 功能 |
---|---|
%s | 字符串 |
%f | 浮点格式,保留小数点位数%.nf,n为数字 |
%b | 相对应的参数中包括转义字符时,可以使用此替换符进行替换,对应的转义字符会被转义 |
%c | ASCII字符,即显示对应参数的第一个字符 |
%d,%i | 十进制整数 |
%o | 八进制值 |
%u | 不带正负号的十进制值 |
%x | 十六进制值(a-f) |
%X | 十六进制值(A-F) |
%% | 表示%本身 |
说明:%s中的数字代表此替换符中的输出字符宽度,不足补空格,默认是右对齐,%-10s表示10个字符宽,-表示左对齐
c.常用转义字符:
转义符 | 功能 |
---|---|
\a | 警告字符,通常为ASCII的BEL字符 |
\b | 后退 |
\f | 换页 |
\n | 换行 |
\r | 回车 |
\t | 水平制表符 |
\v | 垂直制表符 |
\\ | 表示\本身 |
五·Shell脚本语言的运算
1· 算数运算
shell支持算术运算,但只支持整数,不支持小数
2·Bash中的算术运算
运算符号 | 含义 |
+ | 加法运算 |
- | 减法运算 |
* | 乘法运算 |
/ | 除法运算 |
% | 取模,即取余数 |
** | 乘方 |
3·实现算术运算
1. let var=算术表达式
2. var=$[算术表达式]
3. var=$((算术表达式))
4. var=$(expr arg1 arg2 arg3 ...)
5. declare -i var = 数值
6. echo '算术表达式' | bc (支持浮点数)
内建的随机数生成器变量:
$RANDOM 取值范围:0-32767
生成0-49之间的随机数
4· 增强型赋值:
+=
i+=10 <==> i=1+10
-=
i-=j <==> i=i-j
*=
/=
%=
++
i++,++1 <==> i=i+1 (自增)
--
i--,--i <==> i=i-1 (自减)
5· 逻辑运算
True用数字表示1,False用数字表示0
与:&
1 与 1 = 1
1 与 0 = 0
0 与 1 = 0
0 与 0 = 0或:|
1 或 1 = 1
1 或 0 = 1
0 或 1 = 1
0 或 0 = 0非:!
!1 = 0 !True=False
!0 = 1 !False=True异或:^
#异或的两个值,相同为假,不同为真
1 ^ 1 =0
1 ^ 0 =1
0 ^ 1 =1
0 ^ 0 =0
6·短路运算
短路与
CMD1 短路与 CMD2
--第一个CMD1结果为0(假),总的结果必定为0,所以不需要执行CMD2
--第二个CMD1结果为1(真),第二个CMD2必须要参与计算,才能得到最终的结果
短路或
CMD1 短路或 CMD2
--第一个CMD1结果为1(真),总的结果必定为1,因此不需要执行CMD2
--第一个CMD1结果为0(假),第二个CMD2必须要参与运算,才能得到最终的结果
7.条件测试命令
条件测试:判断某需求是否满足,需要由测试机制来实现,专用的测试表达式需要由测试命令辅助完成测试过程,实现评估布尔声明,以便在条件性环境下进行执行。
-
若真,则状态码变量$?返回0
-
若假,则状态码变量$?返回1
文件测试表达式
常用的文件测试操作符 | 说明 |
---|---|
-a/-e 文件 | 文件是否存在 |
-b 文件 | 文件是否存在,且为块文件,如果文件存在且是一个块文件,则结果为0 |
-c 文件 | 文件是否存在且为字符文件,如果文件存在且是一个字符文件,则结果为0 |
-L 文件 或 -h 文件 | 文件存在且为链接文件则为真 |
-d 文件 | 文件存在且为目录则为真,即测试表达式成立 |
-f 文件 | 文件存在且为普通文件则为真,即测试表达式成立 |
-s 文件 | 文件存在且文件大小不为0则为真 |
-S 文件 | 文件是否存在且为套接字文件 |
-p 文件 | 文件是否存在且为管道文件 |
-u 文件 | 文件是否存在且拥有suid的权限,如果设置了suid,则结果为0 |
-g 文件 | 文件是否存在且拥有sgid的权限 |
-r 文件 | 文件存在且可读为真 |
-w 文件 | 文件存在且可写为真 |
-x 文件 | 文件存在且可执行则为真 |
-t fd | fd 文件描述符是否在某终端已经被打开 |
-N 文件 | 文件自从上一次读取之后是否被修改过 |
-O 文件 | 当前有效用户是否为文件属主 |
-G 文件 | 当前有效用户是否为文件属组 |
f1 -ef f2 | 文件f1是否是文件f2的硬链接 |
f1 -nt f2,nt为newerthan | 文件f1比文件f2新则为真,根据文件的修改时间来计算 |
f1 -ot f2,ot为olderthan | 文件f1比文件f2旧则为真,根据文件的修改时间来计算 |
字符串测试表达式
常用字符串测试操作符 | 说明 |
---|---|
-n ”字符串“ | 若字符串的长度不为0,则为真,即测试表达式成立,n可以理解为nozero |
-z ”字符串“ | 若字符串的长度为0,则为真,z可以理解为zero |
> | Ascii码是否大于Ascii码 |
“字符串1” == ”字符串2“ | 若字符串1长度等于字符串2长度,则为真 |
“字符串1” != ”字符串2“ | 若字符串1长度不等于字符串2长度,则为真 |
“字符串1” =~ “字符串2” | 左侧字符串是否能被右侧的PATTERN所匹配。注意:此表达式用于[[ ]]中:扩展的正则表达式 |
整数测试表达式
在[ ] 或 test中使用的比较符号 | 在(()) 或 [[ ]]中使用的比较符号(不用这个做数字比较) | 说明 |
---|---|---|
-eq | \== 或 = | 相等,equal |
-ne | != | 不相等,not equal |
-gt | > | 大于,greater than |
-ge | > = | 大于等于,greater equal |
-lt | < | 小于,less than |
-le | < = | 小于等于,less equal |
逻辑操作符
在[ ] 中使用的操作符 | 在test, [[ ]] , (( ))中使用的逻辑操作符 | 说明 |
---|---|---|
-a | && | and,与,两边都为真,则结果为真 |
-o | || | or,或,有真则真,同假则假 |
! | ! | not,非,两端相反,则结果相反 |
8·关于()与 { }
( )和 { }都可以将多个命令组合再一次,批量执行,{ } 里的内容需要与两侧用空格隔开并在命令结尾加上;
-
( )会开启子shell,并且list中变量赋值及内部命令执行后,将不再影响后续的环境
{ } 不会开启子shell,在当前shell中运行,会影响当前shell环境
9·组合测试条件
a.第一种方式[ ]
[ EXPRESSION1 -a EXPRESSION2] 并且 ==> 条件1与条件2都为真,结果才为真
[ EXPRESSION1 -O EXPRESSION2] 或 ==> 条件1与条件2只要有一个为真,结果就为真
[ !EXPRESSION1 ] 取反说明:-a 和 -o 需要使用测试命令执行,[[ ]] 不支持
b.第二种方式[[ ]]
COMMAND1 && COMMAND2 #并且,短路与,代表条件性的AND THEN
如果COMMAND1 成功,将执行COMMAND2,否则,将不执行COMMAND2COMMAND1 || COMMAND2 #或者,短路或,代表条件性的OR ELSE
如果COMMAND1 成功,将不执行COMMAND2,否则,将执行COMMAND2! COMMAND #非,取反
# 结论:如果&& 和 || 混合使用,&&要在前,||放在后
10.使用read命令命令来接受输入
read 是 Shell 内置命令,用来从标准输入中读取数据并赋值给变量。如果没有进行重定向,默认就是从键盘读取用户输入的数据;如果进行了重定向,那么可以从文件中读取数据
read [option] [variables]
--options表示选项
--variables表示用来存储数据的变量,可以有一个,也可以有多个。
-- options和variables都是可选的,如果没有提供变量名,那么读取的数据将存放到环境变量 REPLY 中。
Option | 说明 |
---|---|
-a array | 把读取的数据赋值给数组array,从下标0开始 |
-d delimiter | 把字符串delimiter指定读取结束的位置,而不是一个换行符(读取的数据不包括delimiter) |
-e | 在获取用户输入的时候,对功能键进行编码转换,不会直接显示功能键对应的字符 |
-n num | 读取num个字符,而不是整行字符 |
-p prompt | 显示提示信息,提示内容为prompt |
-r | 原样读取(Raw mode),不会把反斜杠字符解释为转义字符 |
-s | 静默模式(Silent mode),不会再屏幕上显示输入的字符。例如:输入密码 |
-t seconds | 设置超时时间,单位为秒。如果用户没能按时完成,返回一个非0的退出状态 |
-u fd | 使用文件描述符fd作为输入源,而不是标准输入,类似于重定向 |
只输入一个字符
规定时间输入
超时未输入
六·bash的配置文件
bash shell的配置文件很多,可以分为以下类别
1· 按生效范围划分为两类
全局配置:
/etc/profile
/etc/profile.d/*.sh
/etc/bashrc
个人配置
~/.bash_profile
~/.bashrc
2·shell登录的两种方式分类
交互式登录
-
直接通过终端输入账户密码
-
使用
su - username
切换用户配置文件执行顺序:
/etc/profile --> /etc/profile.d/*.sh --> ~/.bash_profile --> ~/.bashrc --> /etc/bashrc
非交互式登录
-
su username
-
图形界面下打开的终端
-
执行脚本
-
任何其他的bash实例
切换用户配置文件执行顺序:
/etc/profile.d/*.sh --> /etc/bashrc --> ~/.bashrc
3·按功能划分分类
Profile类
profile类为交互式登录的shell提供配置
-
全局:
/etc/profile, /etc/profile.d/*.sh
-
个人:
~/.bash_profile
功能:
-
用于定义环境变量
-
运行命令或脚本
Bashrc类
bashrc类:为非交互式和交互式登录的shell提供配置
-
全局:
/etc/bashrc
-
个人:
~/.bashrc
功能:
-
定义命令别名和函数
-
定义本地变量
4·编辑配置文件生效
source 配置文件
七·流程控制
1·条件选择
选择执行if语句
单分支
双分支
多分支
说明:
-
多个if条件时,逐个条件进行判断,第一次遇见为“真”条件时,执行其分支,而后结束整个if语句
-
if语句可嵌套
条件判断case语句


2·循环
循环执行介绍
将某代码段重复运行多次,通常有进入循环的条件和退出循环的条件
重复运行次数
-
循环次数事先已知
-
循环次数事先未知
常见的循环的命令:for,while
#循环的逻辑:程序先进行语句判断,如果为真则执行循环语句,然后再进行语句判断,直至语句判断失败才跳出
for循环
# 第一种写法
for NAME [in words ...]; do commands;done# 第二种写法
for 变量 in 列表
循环体
done# 第三种写法
for 变量 in 列表
do
循环体
done
执行机制:
依次将列表中的元素赋值给”变量名“;每次赋值后即执行一次循环体;直到列表中的元素耗尽,循环结束
打印9×9乘法表
while循环
while command; do commands;done
while condition;do 循环体 done
condition:循环控制条件;进入循环之前,先做一次判断;每一次循环之后会再次做判断;条件为“Ture”,则执行一次循环;直到条件测试状态为“false”终止循环,因此:condition一般应该有循环控制变量;而此变量的值会在循环不断地被修正
进入条件:condition为True
退出条件:condition为False
案例:数字炸弹
until循环
使用事项
-
until
循环与while
循环类似,不同之处在于until
循环会一直循环,直到条件为真才会停止,而while
会一直循环,直到条件为假才会停止 -
until
循环的语法格式为:until condition; do commands; done
,其中condition
表示循环条件,commands
表示需要执行的命令 -
在
until
循环中,可以使用sleep
命令来延迟循环执行的时间,避免过度消耗系统资源 -
在循环条件中使用
&&
运算符可以将多个条件组合起来,只有当所有条件都满足时,循环才会结束。使用||
运算符可以将多个条件组合起来,只有当任意一个条件满足时,循环才会结束 -
在循环体中使用
break
命令可以提前结束循环 -
在循环体中使用
continue
命令可以跳过当前循环,直接执行下一次循环 -
在使用
until
循环时,要确保循环条件最终能够被满足,否则循环会一直执行下去,直到被手动中断 -
在循环条件中,要使用测试命令或者其他命令来判断条件是否为真,比如使用
[]
或者test
命令来进行比较或者测试 -
在循环体中,可以使用各种 Shell 命令和语句来执行一系列操作,比如打印输出、文件操作、进程管理、网络通信等等
-
until
循环可以用于各种场景,比如等待某个操作完成、等待某个资源可用、等待某个服务启动等等,只需要根据具体需求编写相应的脚本即可
循环控制语句continue
continue[N]:提前结束第N层的本轮循环,而直接进入下一轮判断;最内层为第1层
for (());do
循环体1
...
if command2;then
continue
fi
CMDn
....
done
循环控制语句break
break[N]:提前结束第N层后的全部循环;最内层为第1层,默认为1
八·Shell中的数组
1·Shell数组的概念
数组是若干数据的集合,其中存放的每一份数据都称为元素。Shell
不限制数组的大小,理论上可以存放无限量的数据,Shell
数组元素的下标也是从0开始计数
获取数组中的元素要使用下标[ ],下标可以是一个整数,也可以是一个结果为整数的表达式;下标必须大于等于0
注意:
Shell
只支持一维数组,不支持多维数组
2·Shell数组的定义
数组的基本定义
在Shell
中,用小括号()
来表示数组,数组元素之间用空格来分隔
- #arrayname=(1 2 3 4 5)
-
- 输出定义数组中的全部元素
- #echo ${arrayname[*]}
- #echo ${arrayname[@]}
-
- 输出定义数组中的第二个元素
- #echo ${arrayname[0]}
-
- 输出定义数组中的第二个元素
- #echo ${arrayname[1]}
-
- 输出定义数组中的元素个数
- #echo ${#arrayname[*]}
AI写代码
采用键值对的形式赋值
在Shell
中用小括号将变量括起来,同时采用键值对的形式赋值
- #array2=([1]=one [2]=two [3]=three)
-
- echo ${array2[*]} #输出定义数组的所有元素
-
- echo ${array2[@]} #输出定义数组的所有元素
-
- echo ${#array2[@]} #输出定义数组的元素个数
AI写代码
通过分别定义数组变量的方法来定义
- #array3[1]=a
- #array3[2]=b
- #array3[3]=c
-
- 输出定义数组中的全部元素
- echo ${array3[@]}
-
- 输出定义数组中的第一个元素
- echo ${array3[1]}
AI写代码
动态定义数组数量
动态地定义数组变量,并使用命令的输出结果作为数组的内容
- # mkdir -p /array
- # touch /array/{1..5}.txt
- # ls /array
- # array4=($(ls /array))
- # echo ${array4[*]}
- # echo ${array4[@]}
- # echo ${#array4[*]}
AI写代码
3·Shell数组的打印
-
打印单个数组元素: ${数组名[下标]} 。当未指定数组下标时,下标默认从0开始
-
打印全部数组内容:${数组名[@]}或 ${数组名[*]}
-
打印数组元素的个数:${#数组名[@]}或 ${#数组名[*]}
4·Shell数组的赋值
如果下标不存在,则自动添加一个新的元素;如果下标存在,则覆盖原来的值
5·Shell数组的拼接合并
所谓Shell
数组拼接(数组合并),就是将两个数组连接成一个数组
拼接数组的思路是:先利用@
或者*
,将数组扩展成列表,然后再合并到一起,具体格式如下:
- array_new=(${array1[@]} ${array2[@]})
- array_new=(${array1[*]} ${array2[*]})
- ##两种方式是等价的,选择其一即可。其中,array1 和 array2 是需要拼接的数组,array_new 是拼接后形成的新数组。
AI写代码
6· Shell删除数组元素
在Shell
中,使用unset关键字来删除数组元素,具体格式如下:
- unset array_name[index]
- #其中,array_name表示数组名,index表示数组下标
-
- unset array_name
- #删除整个数组
AI写代码
7·获取数组某范围的元素
在Shell
中直接通过${数组名[@/*]:起始位置:长度}
获取数组给定范围内元素,返回字符串,中间用空格分开
8·数组元素的替换
${数组名[@/*]/查找字符/替换字符}
该操作不会改变原先数组内容,如果需要修改,使用覆盖
9·关联数组
Bash支持关联数组,它可以使用字符串作为数组索引,有时候采用字符串索引更容易理解
定义关联数组
首先需要使用声明语句declare
将一个变量声明为关联数组
# declare -A assArray
声明后,可以有两种方法将添加到关联数组中
利用内嵌索引-值列表的方法
使用独立的索引-值进行赋值
列出数组索引
每一个数组都有一个索引用于查找。使用${!数组名[@/*]}
获取数组的索引列表
# echo ${!assArray[*]}
# echo ${!assArray[@]}
10.mapfile命令
mapfile命令介绍
mapfile
命令用于从标准输入读取行并赋值到数组
mapfile语法结构
mapfile [-d delim] [-n count] [-O origin] [-s count] [-t] [-u fd] [-C callback] [-c quantum] [array]
选项 | 描述 |
-d delim | 将delim设为行分隔符,代替默认的换行符 |
-n count | 从标准输入中获取最多的count行,如果count为0那么获取全部 |
-O origin | 从数组下标为origin的位置开始赋值,默认的下标为0 |
-s count | 跳过对前count行的读取 |
-t | 读取时移除分隔符delim(默认为换行符) |
-u fd | 从文件描述符fd中读取 |
-C callback | 每当读取了quantum行时,调用callback语句 |
-c quantum | 设定读取的行数为quantum |
array(可选) | 用于输出的数组名称。如果没有指定数组名称,那么会默认写入到变量名为MAPFILE的数组中 |
# 如果使用-C时没有同时使用-c指定quantum的值,那么quantum默认为5000。
#当callback语句执行时,将数组下一个要赋值的下标以及读取的行作为额外的参数传递给callback语句。
#如果使用-O时没有提供起始位置,那么mapfile会在实际赋值之前清空该数组
九·Shell中的函数
1·Shell函数的定义
Shell函数的本质是一段可以重复使用的脚本代码,这段代码被提前编好了,放在了指定位置,使用时直接调用即可
Shell 中的函数和C++、Java、Python、C# 等其它编程语言中的函数类似,只是在语法细节有所差别。
Shell 函数定义的语法格式如下:
- function name() {
- statements
- [return value]
- }
AI写代码
对各个部分的说明:
-
function
是 Shell 中的关键字,专门用来定义函数; -
name
是函数名; -
statements
是函数要执行的代码,也就是一组语句; -
return value
表示函数的返回值,其中 return 是 Shell 关键字,专门用在函数中返回一个值;这一部分可以写也可以不写。
由{ }
包围的部分称为函数体,调用一个函数,实际上就是执行函数体中的代码。
函数定义的简化写法
- 1.
- name() {
- statements
- [return value]
- }
- 2.
- function name() {
- statements
- [return value]
- }
AI写代码
2·Shell函数的调用
调用 Shell 函数时可以给它传递参数,也可以不传递。如果不传递参数,直接给出函数名字即可:
name
如果传递参数,那么多个参数之间以空格分隔:
name param1 param2 param3
不管是哪种形式,函数名字后面都不需要带括号。
和其它编程语言不同的是,Shell 函数在定义时不能指明参数,但是在调用时却可以传递参数,并且给它传递什么参数它就接收什么参数。
3·Shell函数详解
Shell中的函数在定义时不能指明参数,但是在调用时却可以传递参数。函数参数是Shell位置参数的一种,在函数内部可以使用$n
来接收,例如:$1
表示第一个参数,$2
表示第二个参数,依次类推
除了$n
,还有另外三个比较重要的变量:
-
$#
可以获取传递的参数的个数; -
$@
或者$*
可以一次性获取所有的参数
扩展:在Shell中 @ 与 @与 @与*的区别
在Shell脚本中,$*和$@是Shell脚本的特殊变量,作用都是获取传递给脚本或函数的所有参数
$@与$*的相同点:当它们没有被双引号包裹时,两者是没有区别的,都代表一个包含接收到的所有参数的数组,各个数组元素都是传入的独立参数
$@与$*的不同点:当被双引号包裹时,$@仍为一个数组,而$*会将所有参数整合成一个字符串
十·Shell高级
Shell的八大扩展功能
花括号
在shell脚本中,可以使用括号对字符串进行扩展,我们可以在一对花括号中包含一组以分号分隔的字符串或者字符串序列组成一个字符串扩展,注意最终输出结果以空格分隔,使用该扩展花括号不可以被引号引用,花括号的数量必须是偶数个
波浪号
波浪号在Shell脚本中默认代表当前用户家目录
变量替换
在Shell脚本中我们会使用 对变量进行扩展替换,变量字符可以放到花括号中,这样可以防止需要扩展的变量字符与其他不需要扩展的字符混淆,如果 对变量进行扩展替换,变量字符可以放到花括号中,这样可以防止需要扩展的变量字符与其他不需要扩展的字符混淆,如果 对变量进行扩展替换,变量字符可以放到花括号中,这样可以防止需要扩展的变量字符与其他不需要扩展的字符混淆,如果后面是位置变量且多余一个数字,必须使用{}
变量替换操作还可以测试变量是否存在及是否为空,若变量不存在或为空,则可以为变量设置一个默认值
Shell脚本支持多种形式的变量测试与替换功能,如下表所示
语法格式 | 功能描述 |
---|---|
${变量:-关键字} | 如果变量未定义或为空,则返回关键字,否则返回变量值 |
${变量:=关键字} | 如果变量未定义或为空,则将关键字赋值给变量,并返回结果,否则直接返回变量值 |
${变量:?关键字} | 如果变量未定义或为空,则通过标准错误显示包含关键字的错误信息,否则返回变量值 |
${变量:+关键字} | 如果变量未定义或为空,则直接返回空,否则返回关键字 |
此外,变量替换还有非常实用的字符串切割与掐头去尾功能
语法格式 | 功能描述 |
---|---|
${变量:偏移量} | 从变量的偏移量位置开始,切割截取变量的值到结尾 |
${变量:偏移量:长度} | 从变量的偏移量位置开始,切割截取特定长度的变量值 |
${变量#关键字} | 用关键字对变量进行模式匹配,从左到右删除匹配到的内容,关键字可以用*表示,使用#匹配时为最短匹配 |
${变量##关键字} | 用关键字对变量进行模式匹配,从左到右删除匹配到的内容,关键字可以用*表示,使用##匹配时为最长匹配 |
${变量%关键字} | 用关键字对变量进行模式匹配,从右到左删除匹配到的内容,关键字可以用*表示,使用%匹配时为最短匹配 |
${变量%%关键字} | 用关键字对变量进行模式匹配,从右到左删除匹配到的内容,关键字可以用*表示,使用%%匹配时为最长匹配 |
变量内容的统计与替换
语法格式 | 功能描述 |
---|---|
${!前缀字符*} | 查找以指定字符开头的变量名称,变量名之间使用IFS分隔 |
${!前缀字符@} | 查找已指定字符开头的变量名称,@在引号中将被扩展为独立的单词 |
${!数组名称[*]]} | 列出数组中所有下标,*在引号中被扩展为一个整体 |
${!数组名称[@]]} | 列出数组中所有下标,@在引号中被扩展为独立的单词 |
${#变量} | 统计变量的长度,变量可以是数组 |
${变量/旧字符串/新字符串} | 将变量中的旧字符串替换为新字符串,仅替换第一个 |
${变量//旧字符串/新字符串} | 将变量中的旧字符串替换为新字符串,替换所有 |
${变量^匹配字符} | 将变量中的小写替换为大写,仅替换第一个 |
${变量^^匹配字符} | 将变量中的小写替换为大写,替换所有 |
${变量,匹配字符} | 将变量中的大写替换为小写,仅替换第一个 |
${变量,匹配字符} | 将变量中的大写替换为小写,替换所有 |
命令替换
#我们可以通过$(命令)或`命令`方式实现替换
算数替换
通过算数替换阔可以进行算数计算并返回计算结果,算数替换扩展的格式为$(())
,也可以使用$[]
的方式,算数扩展支持嵌套
进程替换
进程替换将进程的返回结果通过命令管道的方式传递给另一个进程
语法格式为:<(命令)或者>(命令)
一旦使用了进程替换功能,系统将会在/dev/fd目录下创建文件描述符文件,通过该文件描述符将进程的输出结果传递给其他进程
Linux系统中可以使用管道将前一个命令输出重定向到文件,但是一旦使用了重定向输出到文件,输出结果无法在屏幕上显示
单词切割
单词切割又叫做分词,Shell使用IFS变量进行分词处理。如果没有自定义IFS变量,默认为空格,Tab制表符,换行符
路径替换
除非使用set -f
禁用路径替换,否则bash会在路径和文件名中搜索*、?和[符号,如果找到了这些符号则进行模式匹配的替换。
使用shopt
命令时开启了nocaseglob
选项,则bash的进行模式匹配时不区分大小写,默认区分大小写。
此外还可以开启extglob
选项,让bash支持扩展通配符。
shopt
命令-s选项可以开启特定的Shell属性,-u选项可以关闭特定的Shell属性
basename
和dirname
:
basename
:可以获取一个路径中的文件名
dirname
:仅保留路径,删除文件名
十一·Shell编程之正则表达式
1·正则表达式
概述
正则表达式通常用于判断语句中,用来检查某一字符串是否满足某一格式。
正则表达式是由普通字符与元字符组成。普通字符包括小写字母、数字、标点符号及一些其他符号。元字符是指在正则表达式中具有特殊意义的专用字符,可以用来规定其前导字符(即位于元字符前面的字符)在目标对象中的出现模式。
分类
正则表达式根据从POSIX BRE或者POSIX ERE标准可以分为基本正则表达式和扩展正则表达式。
基本正则表达式
支持的工具:grep
、egrep
、sed
、 awk
,注意grep
要配合-E
或者-P
使用。
元字符 | 含义及用法 |
---|---|
\ | 转义字符,用于取消特殊符号的含义,例: \! 、 \n 、 \$ 等 |
^ | 匹配字符串开始的位置,例:^a 、^the 、^# 、^[a-z] |
$ | 匹配字符串结束的位置,例: word$ 、^$ 匹配空行 |
. | 匹配除\n 之外的任意的一个字符,例: go.d 、g..d 。如果想要匹配包含\n字符可以使用 [.\n] |
* | 匹配前面子表达式0次或者多次,例: goo*d 、 go.*d |
[list] | 匹配list列表中的一个字符,例: go[ola]d ,[abc] 、[a-z] 、[a-z0-9] 、[0-9] 匹配任意一位数字 |
[^list] | 匹配任意非list列表中的一个字符,例:[^0-9] 、[^A-Z0-9] 、[^a-z] 匹配任意一位非小写字母 |
\{n\} | 匹配前面的子表达式n次,例: go\{2\}d 、 [0-9]\{2\} 匹配两位数字 |
\{n,\} | 匹配前面的子表达式不少于n次,例: gol{2,l}d 、[0-9]\{2,\} 匹配两位及两位以上数字 |
\{n,m\} | 匹配前面的子表达式n到m次,例 : go\{2,3\}d 、[0-9]\{2,3\} 匹配两位到三位数字 |
注: egrep 、 awk 使用{n} 、{n,} 、{n,m} 匹配时 {} 前不用加 \ | |
\w | 匹配包括下划线的任何单词字符。 |
\W | 匹配任何非单词字符。等价于[^A-Za-z0-9_] 。 |
\d | 匹配一个数字字符。 |
\D | 匹配一个非数字字符。等价于[^0-9] 。 |
\s | 空白符。 |
\S | 非空白符。 |
扩展正则表达式
支持的工具:egrep
、awk
,注意:使用grep
要配合-E
或者-P
使用,sed
要配合-r
使用。
元字符 | 含义及用法 |
---|---|
+ | 匹配前面子表达式1次以上,例: go+d ,将匹配至少一个o ,如god 、good 、goood 等 |
? | 匹配前面子表达式0次或者1次,例: go?d ,将匹配gd 或god |
() | 将括号中的字符串作为一个整体,例1: g(oo)+d ,将匹配oo 整体1次以上,如good 、gooood 等 |
| | 以或的方式匹配字符串,例:g(oo|la)d ,将匹配good 或者 glad |
正则表达式的使用
* ^ $的用法
#查询一串字符中有goo*d字样,且o有0个或多个,此字符串可以不在开头或结尾
#查询以g开头d结尾,中间的o有0个或多个
[] [^]的用法
#查询一个字符,其中有一段以go开头d结尾,中间的o、l、a这几种字符中的一种
#查询一个字符,其中有一段以go开头d结尾,中间的o、l、a这几种字符中的一个或多个
#匹配除了a-g开头的字符
\{n\} \{n,\} 的用法
#匹配good字符,其中\{2\}只会匹配前面的o两次
#匹配go..d,其中o至少2次及以上
常见例题
电话例题
找出区号025开头的号码,且号码与区号间可以是空格、-、没有,号码必须是5或者8开头的八位数。
电子邮箱例题
根据 用户名@子域名.[二级域名].顶级域
格式找出符合要求的电子邮箱
用户名@:长度要求在6-18位,任意大小写英文,任意数字,除了@符号和空格以外的其它任意符号字符,开头只能是 _ 或者字母
子域名.[二级域名]:长度任意,符号只能包含 - _ .
.顶级域名: 长度在2-5,任意大小写英文
十二·sed编辑器
1.sed编辑器概念
sed是一种流编辑器,流编辑器会在编辑器处理数据之前基于预先提供的一组规则来编辑数据流。
sed编辑器可以根据命令来处理数据流中的数据,这些命令要么从命令行中输入,要么存储一个命令文本文件中。
2.sed编辑器工作流程
sed 的工作流程主要包括读取、执行和显示三个过程:
读取:sed从输入流(文件、管道、标准输入〉中读取一行内容并存储到临时的缓冲区中(又称模式空间,pattern space)。 执行:默认情况下,所有的sed命令都在模式空间中顺序地执行,除非指定了行的地址,否则临时sed命令将会在所有的行上依次执行。
显示:发送修改后的内容到输出流。在发送数据后,模式空间将会被清空。
在所有的文件内容都被处理完成之前,上述过程将重复执行,直至所有内容被处理完。
注意:默认情况下所有的sed命令都是在模式空间内执行的,因此输入的文件并不会发生任何变化,除非是用重定向存储输出。
处理大文件较卡问题
流编辑器处理大文件比较卡可以使用两种方式来处理。sed命令将大文件分成若干个小文件读取。或者使用cat
命令读取全部文件放在临时缓冲区中,然后交给流编辑器(grep、sed、awk)进行处理,由于使用cat命令时IO消耗比较低。
3.sed编辑器用法
命令格式
sed -e '操作' 文件l 文件2 ...
sed -n -e '操作' 文件1 文件2 ...
sed -f 脚本文件 文件1 文件2 ...
sed -i -e '操作' 文件1 文件2 ...sed -e 'n{ #n意为:指定行
操作l
操作2
...
}' 文件1 文件2 ...
sed 允许使用几乎任何字符作为模式分隔符,常见的替代符号
|
示例:sed 's|/usr/bin|/usr/1ocal/bin|g’替换 /usr/bin为/usr/local/bin。
#
示例:sed 's#/old/path#/new/path#g‘避免转义路径中的斜杠。
:
示例:sed 's:/old:/new:g’适用于路径替换。
%示例例:sed 's%o1d%new%g‘
简洁的分隔符。
@示例:sed 's@old@new@g’
常用于电子邮件或 URL 处理。
常用选项
选项 | 含义 |
---|---|
-e 或--expression= | 表示用指定命令来处理输入的文本文件,只有一个操作命令时可省略,一般在执行多个操作命令使用。 |
-f 或--file= | 表示用指定的脚本文件来处理输入的文本文件。 |
-h 或--help | 显示帮助。 |
-n 、--quiet 或silent | 禁止sed编辑器输出,但可以与p 命令一起使用完成输出。 |
-i | 直接修改目标文本文件。 |
-r, --regexp-extended | 支持正则表达式 |
常用操作
操作 | 含义 |
---|---|
s | 替换,替换指定字符。 |
d | 删除,删除选定的行。 |
a | 增加,在当前行下面增加一行指定内容。 |
i | 插入,在选定行上面插入一行指定内容。 |
c | 替换,将选定行替换为指定内容。 |
y | 字符转换,转换前后的字符长度必须相同。 |
p | 打印,如果同时指定行,表示打印指定行;如果不指定行,则表示打印所有内容,如果有非打印字符,则以ASCII码输出。其通常与-n 选项一起使用。 |
= | 打印行号。 |
l (小写L) | 打印数据流中的文本和不可打印的AscII字符(比如结束符$ 、制表符\t ) |
常用方式
打印内容
#打印内容
#打印行号
#打印隐藏特殊符号
#打印行号和内容
sed编辑器的寻址方式
-
以数字形式表示行区间
-
用文本模式来过滤出行
#打印第1行
#打印最后一行
#从第3行开始打印,直到最后一行结束
#打印偶数行
#打印包含user的行
删除行内容
#删除以nologin结尾的文件
#"!"表示取反
替换内容
#将匹配行中第一个root替换为admin然后打印替换的行
插入内容
#将含有goo的行都替换为ABC
十三·awk编辑器
1.概念
sed命令常用于一整行的处理,而awk比较倾向于将一行分成多个"字段"然后再进行处理。awk信息的读入也是逐行读取的,执行结果可以通过print
的功能将字段数据打印显示。
在使用awk命令的过程中,可以使用逻辑操作符 &&
表示与、||
表示或、!
表示非;还可以进行简单的数学运算,如+
、-
、*
、/
、%
、^
分别表示加、减、乘、除、取余和乘方。
2.工作原理
逐行读取文本,默认以空格或tab键为分隔符进行分隔,将分隔所得的各个字段保存到内建变量中,并按模式或者条件执行编辑命令。
3.用法
命令格式
awk 选项 '模式或条件 {操作}' 文件1 文件2 ...
awk -f 脚本文件 文件l 文件2 ...
常用选项
-F 指定分隔符
awk -F ',' '{print}' file1
常见的内建变量
内建变量 | 含义 |
---|---|
FS | 列分割符。指定每行文本的字段分隔符,默认为空格或制表位。与-F 作用相同。 |
NF | 当前处理的行的字段个数。$NF 代表最后一个字段。 |
NR | 当前处理的行的行号(序数)。 |
$0 | 当前处理的行的整行内容。 |
$n | 当前处理行的第n个字段(第n列)。 |
FILENAME | 被处理的文件名。 |
RS | 行分隔符。awk从文件上读取资料时,将根据Rs的定义把资料切割成许多条记录,而awk比较倾向于将一行分成多个一次仅读入一条记录,以进行处理。预设值是\n 。 |
常用方式
按行输出文本
输出指定行内容
###输出第1~3行内容
输出奇偶数行的内容
###输出偶数行的内容
###输出奇数行的内容
输出含有字符串的行
###输出含有root的行
###输出以nologin结尾的行
按字段输出文本
输出每行中(以控股或制表位分隔)的第3个字段
输出特定条件的行的字段内容
###输出第3个字段的值小于5的第1、3个字段内容
输出每行内容和行号,每处理完一条记录,NR值加1
输出两种指定条件的内容
##输出以冒号分隔且第7个字段中包含/bash的行的全部内容
通过管道、双引号调用 Shell命令
调用wc -l命令统计使用bash 的用户个数
查看当前内存使用百分比
查看当前CPU空闲率
查看当前磁盘的情况
获取奇偶数行
获取奇数行
当getline
左右无重定向符<
或|
时,awk首先读取到了第一行,就是1,然后使用getline
就得到了1下面的第二行,就是2,因为getline
之后,awk会改变对应的NF
,NR
,FNR
和$0
等内部变量,所以此时的$0
的值就不再是1,而是2了,然后将它打印出来。
当getline
左右有重定向符<
或|
时,getline则作用于定向输入文件,由于该文件是刚打开,并没有被awk读入一行,只是getline读入,那么getline返回的是该文件的第一行,而不是隔行。
查看使用特定分隔符的字符串
#输出ABCD字符串以及用|分隔的字符串
OFS是列输出分隔符,可以用来指定分隔符。
$1=$1
是用来激活$0
的重新赋值,也就是说字段$1
…和字段数NF的改变会促使awk重新计算$0
的值,通常是在改变OFS后而需要输出$0
时这样做。
按数组输出文本以及统计
下标是数字时输出文本
其中字符串需要用双引号包起来。
下标是数字,使用循环输出文本(其中BEGIN中的命令只执行一次 )
统计重复字符串的数量以及输出对应的字符串
a[1]
初始为0,a[1]++
后即为1,而这里awk中的a[1]++
最终的值是由num.txt文本内容有多少行决定的,文本逐行读取完毕后再执行END中的命令。
十四·find命令详解
find命令是Unix和类Unix系统中一个强大的文件搜索工具,它允许用户在文件系统中按照不同的条件查找文件和目录。由于其灵活性和功能强大,find命令成为系统管理员和开发人员在维护文件系统和查找特定文件时的首选工具。本文将深入介绍find命令的基本语法、常用选项以及高级用法,以帮助读者更全面地了解和使用这个重要的Unix命令。
1、find基本语法
find命令的基本语法如下:
find [path...] [expression]
其中,path是查找的起始路径,可以是目录名、文件名或通配符。expression是用于指定搜索条件的表达式,它可以包含多个选项和操作符。
2、常用选项
选项 | 作用 |
---|---|
-amin<分钟> | 查找在指定时间曾被存取过的文件或目录,单位以分钟计算; |
- anewer<参考文件或目录> | 查找其存取时间较指定文件或目录的存取时间更接近现在的文件或目录; |
- atime<24小时数> | 查找在指定时间曾被存取过的文件或目录,单位以24小时计算; |
- cmin<分钟> | 查找在指定时间之时被更改过的文件或目录; |
- cnewer<参考文件或目录> | 查找其更改时间较指定文件或目录的更改时间更接近现在的文件或目录; |
- ctime<24小时数> | 查找在指定时间之时被更改的文件或目录,单位以24小时计算; |
- daystart | 从本日开始计算时间; |
- depth | 从指定目录下最深层的子目录开始查找; |
- expty | 寻找文件大小为0 Byte的文件,或目录下没有任何子目录或文件的空目录; |
- exec<执行指令> | 假设find指令的回传值为True,就执行该指令; |
- false | 将find指令的回传值皆设为False; |
- fls<列表文件> | 此参数的效果和指定“ - ls”参数类似,但会把结果保存为指定的列表文件; |
- follow | 排除符号连接; |
- fprint<列表文件> | 此参数的效果和指定“ - print”参数类似,但会把结果保存成指定的列表文件; |
- fprint0<列表文件> | 此参数的效果和指定“ - print0”参数类似,但会把结果保存成指定的列表文件; |
- fprintf<列表文件><输出格式> | 此参数的效果和指定“ - printf”参数类似,但会把结果保存成指定的列表文件; |
- fstype<文件系统类型> | 只寻找该文件系统类型下的文件或目录; |
- gid<群组识别码> | 查找符合指定之群组识别码的文件或目录; |
- group<群组名称> | 查找符合指定之群组名称的文件或目录; |
- help或——help | 在线帮助; |
- ilname<范本样式> | 此参数的效果和指定“ - lname”参数类似,但忽略字符大小写的差别; |
- iname<范本样式> | 此参数的效果和指定“ - name”参数类似,但忽略字符大小写的差别; |
- inum<inode编号> | 查找符合指定的inode编号的文件或目录; |
- ipath<范本样式> | 此参数的效果和指定“ - path”参数类似,但忽略字符大小写的差别; |
- iregex<范本样式> | 此参数的效果和指定“ - regexe”参数类似,但忽略字符大小写的差别; |
- links<连接数目> | 查找符合指定的硬连接数目的文件或目录; |
- iname<范本样式> | 指定字符串作为寻找符号连接的范本样式; |
- ls | 假设find指令的回传值为Ture,就将文件或目录名称列出到标准输出; |
- maxdepth<目录层级> | 设置最大目录层级; |
- mindepth<目录层级> | 设置最小目录层级; |
- mmin<分钟> | 查找在指定时间曾被更改过的文件或目录,单位以分钟计算; |
- mount | 此参数的效果和指定“ - xdev”相同; |
- mtime<24小时数> | 查找在指定时间曾被更改过的文件或目录,单位以24小时计算; |
- name<范本样式> | 指定字符串作为寻找文件或目录的范本样式; |
- newer<参考文件或目录> | 查找其更改时间较指定文件或目录的更改时间更接近现在的文件或目录; |
- nogroup | 找出不属于本地主机群组识别码的文件或目录; |
- noleaf | 不去考虑目录至少需拥有两个硬连接存在; |
- nouser | 找出不属于本地主机用户识别码的文件或目录; |
- ok<执行指令> | 此参数的效果和指定“ - exec”类似,但在执行指令之前会先询问用户,若回答“y”或“Y”,则放弃执行命令; |
- path<范本样式> | 指定字符串作为寻找目录的范本样式; |
- perm<权限数值> | 查找符合指定的权限数值的文件或目录; |
假设find指令的回传值为Ture,就将文件或目录名称列出到标准输出。格式为每列一个名称,每个名称前皆有“. / ”字符串; | |
- print0 | 假设find指令的回传值为Ture,就将文件或目录名称列出到标准输出。格式为全部的名称皆在同一行; |
- printf<输出格式> | 假设find指令的回传值为Ture,就将文件或目录名称列出到标准输出。格式可以自行指定; |
- prune | 不寻找字符串作为寻找文件或目录的范本样式; |
-regex<范本样式> | 指定字符串作为寻找文件或目录的范本样式; |
- size<文件大小> | 查找符合指定的文件大小的文件; |
- true | 将find指令的回传值皆设为True; |
- type<文件类型> | 只寻找符合指定的文件类型的文件; |
- uid<用户识别码> | 查找符合指定的用户识别码的文件或目录; |
- used<日数> | 查找文件或目录被更改之后在指定时间曾被存取过的文件或目录,单位以日计算; |
- user<拥有者名称> | 查找符和指定的拥有者名称的文件或目录; |
- version或——version | 显示版本信息; |
- xdev | 将范围局限在先行的文件系统中; |
- xtype<文件类型> | 此参数的效果和指定“ - type”参数类似,差别在于它针对符号连接检查。 |
2.1 示例:查找大于1MB的文件
上述命令将在指定路径下查找所有大小大于1MB的文件。
2.2 示例:查找最近7天内修改过的文件
这个例子将在指定路径下查找最近7天内修改过的文件。
2.3 示例:查找属主为user1的文件
上述命令将在指定路径下查找所有属主为user1的文件。
2.4 示例:执行自定义命令
find /path/to/search -name "*.log" -exec rm {} \;
这个例子将删除指定路径下所有扩展名为.log的文件。
十五、脚本案例
1.自动备份文件或目录:
2.批量重命名文件
3.批量删除文件
4查找并删除指定名称的文件:
5.查找并替换文件内容:
- #!/bin/bash
-
- # 设置要查找的字符串
- search_string="old_string"
-
- # 设置要替换成的字符串
- replace_string="new_string"
-
- # 查找并替换文件内容
- find . -type f -exec sed -i "s/${search_string}/${replace_string}/g" {} \;
AI写代码
6.批量创建文件:
7·创建文件夹并移动文件:
8.在文件夹中查找文件:
9.计算文件夹中文件数量:
10.计算文件夹大小:
11.定时执行命令:
- #!/bin/bash
-
- # 设置命令
- command="echo hello"
-
- # 设置执行周期(以秒为单位)
- period=10
-
- # 定时执行命令
- while true
- do
- eval ${command}
- sleep ${period}
- done
AI写代码
12.发送邮件:
- #!/bin/bash
-
- # 设置收件人邮箱
- to="recipient@example.com"
-
- # 设置发件人邮箱
- from="sender@example.com"
-
- # 设置邮件主题
- subject="Test Email"
-
- # 设置邮件内容
- body="This is a test email."
-
- # 发送邮件
- echo "${body}" | mail -s "${subject}" -r "${from}" "${to}"
AI写代码
13.批量解压缩文件:
14.在文件夹中查找并删除文件:
15.批量重命名文件:
16.对文件夹中的文件按修改时间排序:
17.批量转换文件格式:
注意:需要先安装Pandoc。
18.删除文件夹中的空文件:
19.删除文件夹中的空文件夹:
20.批量更改文件权限:
21.使用awk分隔文件
总结
今天的知识都是基础理解的知识,需要记忆一些常用的命令,为后续语句的学习打下基础。
今日更新了条件语句和循环语句,结合之前的命令可以写一些简单的脚本,之后的更新会出一些实战例题来练习语句的使用。
今日重点是数组还有函数的使用,加上一些符号的使用,已经可以编写不少脚本了,会额外开一篇番外编写项目脚本实战,之后最重要的是正则的学习。
终于结束了shell脚本的学习,这一部分内容还是挺难得,要勤加练习。