ubuntu下第一个的shell脚本"细胞分裂"
关于终端输入执行的一般逻辑,貌似如此:
(这些逻辑对特殊的例如if之类的不管用)
字符串1 空格 字符串2 空格 字符串3.....
字符串1被识别成指令,后面是传入参数,它们间用空格隔开。
如果是这样 空格xN 字符串1 空格 字符串2 空格 字符串3.....
字符串1依旧是命令,后面是参数。


字符串1 空格 $字符串2 空格 字符串3.....
字符串1是命令,字符串2前面加上$,如果某个变量名(变量名必须是英文)等于"字符串2",那么传入参数1是这个变量的值。

字符串1 空格 $(字符串2) 空格 字符串3.....
传入参数1是指令"字符串2"的输出值。(括号内必须是指令,否则会出错)

字符串1 ; 字符串2
如果两个字符用分号隔开如上,那么字符串1和字符串2都是指令

按如上逻辑来解释下面的命令

音乐/CloudMusic下不存在文件,所以指令ls的输出结果必然是空字符串。
-z是"["指令的参数,用来判断字符串长度是否为0,字符串长度为0,则整个指令输出1,否则为0。
先看看关于if语句的逻辑,貌似是这样:
if 指令
then
指令1
else
指令0
fi
关键字if加空格隔开后跟着一个指令,如果这个指令输出1就执行then命令下的指令1,否则就执行else指令下的指令0,fi是if语句结束指令,fi实际上就是if反过来写,case语句的结束指令esac也是case反过来写。
根据大神的文章(详见https://www.cnblogs.com/include/archive/2011/12/09/2307905.html)
"["是一个命令,[...]里面的内容是命令的参数,"]"应该是命令的结束符号(我猜的)

第一段判断逻辑:
if和[...]用空格隔开,if是指令?"["是指令,[...]里的内容是参数,"["得与参数用空格隔开,参数之间也得用空格隔开,否则会发生不可名状的错误。
[...]内的参数"ls"是字符串,它不为空,所以输出结果为
Exist(存在)
第二段判断逻辑:
$(ls)是指令ls的输出结果,它是空,所以输出结果为
Null(空)
第三段判断逻辑:
在判断前,我们在工作目录下创建了一个文件
$(ls)是指令ls的输出结果,它现在不为空,所以输出结果为
Exist(存在)
关于shell脚本与shell指令:
shell翻译作壳、贝壳等,shell是用户与内核进行交互的接口
pwd、vi、gcc、sudo、mv、echo等都是shell指令
我们可以扩充shell,获得更多的shell指令。
shell脚本实际上就是有序地执行一系列shell指令,它本身也算是shell指令
使用shell指令echo在终端打印"师姐,你好!":
在安装系统的时候我们选择了简体中文语言,一般来说安装程序会为我们安装中文输入法,我们只需要按win+空格键就可以切换输入法了!
echo "师姐,你好!"

使用shell指令创建变量a并为其赋值10:
直接赋值:
a=10给a赋值10
$a 读取变量a的值

在赋值时不能随意加入空格,例如a =10,按照最开始的说法,a是指令,=10是指令a的传参
read指令赋值:
read -p "请输入一个值" a

命令的结果作为变量的值:
a=$(ls -l | grep ^- |wc -l')a的值为工作目录下普通文件的个数

其他几种赋值方式就不讨论了,因为我不会
使用shell指令cp将工作目录下的文件HW复制到其子目录文档下并命名为HWcp:
cp HW 文档/HWcp


Linux系统中的文件类型及其标识符
普通文件,标识符:-
目录文件,标识符:d (Directory)
符号链接文件,标识符:l (Link)
块文件,标识符:b (Block)
管道文件,标识符:p (Pipe)
套间字,标识符:s (Socket)
使用shell指令ls -l (list -long)显示工作目录下的详细信息:

一行表示一个文件,某行首字符是此行文件的文件类型标识符
使用shell指令grep来筛选:
来自CSDN大神https://blog.csdn.net/chen1415886044/article/details/107116370

grep 师姐 师姐好.c 在师姐好.c文件中寻找含有子串"师姐"的所有行并输出到终端上:


grep ^# 师姐好.c 在师姐好.c文件中搜索行首首字符为#的行并输出到终端上

shell指令中的符号|:
|意思为将前一个指令的输出参数作为下一个指令的输入参数,例如
ls -l | grep ^- 将ls -l输出作为grep指令的第二个传参(第一个参数是^-),此指令作用是获得工作目录下普通文件的信息
ls -l | grep ^- | wc -l 此指令作用是统计工作目录下普通文件的数量



更多符号的含义:来自CSDN大神https://blog.csdn.net/weixin_43972437/article/details/112606169

编写第一个shell脚本:
shell脚本的后缀名为.sh,我们使用vim编辑器创建一个名为cell0.sh的shell脚本,

第一行表示此脚本shell指令的路径

我们写下如上图的指令,$0的值是脚本本身,$1是脚本传入的第一个参数,$2是第二个........
$@的作用是显示所有传参
我们规定所有的细胞脚本的命名规则为:"cell"+"某个数字"
所以ls -l | grep cell |wc -l指令能输出工作目录下的细胞脚本总数
我们用变量N来存储工作目录下的细胞脚本数,然后保存先试着运行一下脚本

当然这时候运行脚本也可能会提示和权限有关的错误,这可能是因为我们没有这个文件的执行权限,所以它现在对于我们来说还不是可执行文件,我们用指令sudo chmod 700给用户赋予此文件的所有权限并关闭G(Group,意为自己的用户组)组和O(Other,翻译为其他)用户的权限。(注意shell脚本权限,即便脚本不具有破坏性,我们也不希望任何人都有执行它的权限)
再写一个交互指令,用read指令来读取用户的选择,并使用if语句来输出用户的选择

文章最开始已经讨论过if命令了,注意空格,==也是传参,也得用空格隔开,否则将会发生不可名状的错误

OK,写到这里,可以将这些代码都删了(除了统计细胞个数的代码),这些只是用来练练手,熟悉一下shell语法用的。
接下来来实现我们的逻辑吧!
首先写两个细胞分裂的逻辑,第一个细胞分裂是自分裂,也就是当前细胞脚本自身是否复制一份,我们用传入参数1来控制,传入"y"表示启用自分裂,否则没有动作,第二个细胞分裂是控制当前目录下所有细胞的自分裂,传入"y"表示启动所有细胞自分裂。
这两个逻辑都很简单,自分裂逻辑中还加入了数量限制

我们执行0号细胞脚本,给它传入 n y,首先它会统计当前目录下细胞个数,然后用for语句将这些细胞都启动自分裂也就是 "./cell$i.sh",这样做有一个好处,那就是新分裂的细胞不会被执行,同时刚执行0号细胞脚本时,它不会自分裂,它会在启动全局分裂时和工作目录下的其他细胞一起自分裂。
这样我们可以控制单个细胞的分裂和全部细胞的分裂。由于这样的逻辑依赖于细胞脚本的名字(主要是索引),如果在分类的过程中,用户将某些细胞删除了,此时再进行全局分裂可能出现一点小问题,所以我又加入了重排列函数,在执行自分裂前先重排列,我用第三个传参控制是否执行重排列。

将4、5号细胞移动到别的目录后,此时剩下6个细胞,再次执行全局分裂

分裂完成后有12个细胞,由于我加入了重排列逻辑,所以4、5又出现了,他们是由6、7号变的,重排列的逻辑也很简单,对!就是聪明的你所想的那样!
也可以加入定时逻辑,让分裂自动执行、让它具有周期性。
最好再加入刽子手细胞,一键即可杀死所有细胞,当然这里的空白太小了,我已经写不下了,到此为止!