软链接是文件名的链接,也可以驻留在不同的文件名中; 但硬链接链接到文件的inode,并且必须与文件的文件系统相同。删除原始文件会使软链接处于非活动状态(断开链接),但不会影响硬链接(硬链接仍将访问该文件的副本)
默认情况下,ln命令产生硬链接
硬链接指向一个 inode 节点,而软链接则是创建一个新的 inode 节点。
硬链接:
①不允许给目录创建硬链接。
②只有在同一文件系统中的文件之间才能创建链接。 即不同硬盘分区上的两个文件之间不能够建立硬链接。这是因为硬链接是通过结点指向原始文件的,而文件的i-结点在不同的文件系统中可能会不同。
Linux操作可以对目录进行硬链接? 不可以
软链接:
软连接就相当于我们win中的快捷方式即如果你软连接一个目录只是一个目录的快捷方式到指定位置,操作系统找这个快捷方式会直接找到真实目录下的文件
ln -s
#!/bin/bash
read -p “Input file name:” FILENAME
if [ -c “$FILENAME”];then
cp $FILENAME /dev
fi
[ 条件测试
[ -d DIR ] 如果DIR存在并且是一个目录则为真
[ -f FILE ] 如果FILE存在且是一个普通文件则为真
[ -z STRING ] 如果STRING的长度为零则为真
[ -n STRING ] 如果STRING的长度非零则为真
[ STRING1 = STRING2 ] 如果两个字符串相同则为真
[ STRING1 != STRING2 ] 如果字符串不相同则为真
[ ARG1 OP ARG2] ARG1和ARG2应该是整数或者取值为整数的变量
OP是-eq(等于) -ne(不等于) -lt(小于) -le(小于等于) -gt(大于) -ge(大于等于)
带与、或、非的测试命令
EXPR可以是上表中的任意一种测试条件
[ ! EXPR ]
[ EXPR1 -a EXPR2] -a表示逻辑与
[ EXPR1 -o EXPR2] -o表示逻辑或
例如:
$ VAR=abc
$ [ -d Desktop -a "$VAR" = 'abc' ] ❤
$ echo $?
0
注意:作为一种好的Shell编程习惯,应该总是把变量取值放在双引号之中。 避免因变量事先没有定义,则被Shell展开为空字符串而造成测试条件的语法错误
配合if语句
if [ $a -eq $b ]
then
echo "$a -eq $b : a 等于 b"
else
echo "$a -eq $b: a 不等于 b"
fi
3.字符串运算符
[ = ] 是字符串比较, [ == ]是数值比较
grep -n '\.$' test.txt | wc -l
[root@aliyun ~]# cat test.txt
My name is fruit,
I am now working at HS in Hangzhou as a intern.
I am so sad failed in the Sangfor final test,
but I got the green card about autumn recruitment in 2020.
I still have a chance to try it!
Break a leg in 2020.
[root@aliyun ~]# grep -n '\.$' test.txt
2:I am now working at HS in Hangzhou as a intern.
4:but I got the green card about autumn recruitment in 2020.
7:Break a leg in 2020.
[root@aliyun ~]# grep -n '\.$' test.txt | wc -l
3
涉及知识点
正则表达式
^ 匹配行首的位置 ^Content匹配位于一行开头的Content
$ 匹配行末的位置 ;$匹配位于一行结尾的;号,^$匹配空行
[^ ] 位于[]括号内的开头,匹配除括号中的字符之外的任意一个字符 [^xy]匹配除xy之外的任一字符
原文链接:https://blog.csdn.net/qq_39578545/article/details/104902554
grep
-a :将 binary 文件以 text 文件的方式搜寻数据
-c :计算找到 '搜寻字符串' 的次数
-i :忽略大小写的不同,所以大小写视为相同
-n :顺便输出行号
-v :反向选择,亦即显示出没有 '搜寻字符串' 内容的那一行
-w : 作为整个单词进行匹配
-o : 只显示匹配内容
空白行:
grep -n '^$' test.txt
给定一个文件找到包含单词"ABC”的行数。
grep -c "ABC" file1
wc
wc 有四个参数可选,分别是l,c,m,w
wc -l filename 报告行数
wc -c filename 报告字节数
wc -m filename 报告字符数
wc -w filename 报告单词数
对文件test.txt统计行数
wc -l test.txt
统计当前文件夹下的文件占用的字节数
ls -l | wc -c
统计当前目录下的文件数
ls -l | wc -l
for i in {1..20}
do
username=user$i
passwd="user`cat /dev/random | head -1 | md5sum | head -c 5`"
useradd $username
echo "$passwd" | passwd --stdin $username
echo "$username--$passwd" >> user.txt
done
生成随机字符方法:
cat /dev/random | head -1 | md5sum | head -c 5
非交互式设置密码
echo “新密码”|passwd --stdin 用户名
[root@aliyun ~]# echo “qwert” | passwd --stdin hehe
更改用户 hehe 的密码 。
passwd:所有的身份验证令牌已经成功更新。
交互式设置密码:
[root@aliyun ~]# passwd hehe
Enter new password:
#!/bin/bash
groupadd class
for i in {class01..class30}; do
xx=`echo $i | sed 's/class//g'`
useradd -g class -s /bin/bash -d /home/std$xx -m std$xx
echo -e "std$xx@123456" | passwd std$xx
echo -e "user std$xx password is std$xx@123456" >> /root/newuser.txt
done
-s是指定用户登入后所使用的shell。默认值为/bin/bash。如果不想让用户登录系统可以用 -s /sbin/nologin.此用户就不可以登录系统。
-d:指定用户登入时的主目录,替换系统默认值/home/<用户名>
-m:自动建立用户的登入目录。
#!/bin/bash
for i in {9901..9930}; do
xx=`echo $i | sed 's/99//g'`
userdel -r std$xx
done
-r代表把用户相对应的目录一并删除
$# $0 $@ $$ $?
$# 是传给脚本的参数个数计数
$0 是脚本本身的名字
$1 是传递给该shell脚本的第一个参数
$2 是传递给该shell脚本的第二个参数
$@ 是传给脚本的所有参数的列表
$* 是以一个单字符串显示所有向脚本传递的参数,与位置变量不同,参数可超过9个
$$ 是脚本运行的当前进程ID号
$? 是显示最后命令的退出状态,0表示没有错误,其他表示有错误
#!/bin/sh
echo "number:$#"
echo "scname:$0"
echo "first :$1"
echo "second:$2"
echo "argume:$@"
echo "show parm list:$*"
echo "show process id:$$"
echo "show precomm stat: $?"
保存退出
赋予脚本执行权限
# chmod +x test
执行脚本
# ./test aa bb
number:2
scname:./variable
first:aa
second:bb
argume:aa bb
show parm list:aa bb
show process id:24544
show precomm stat:0
https://www.cnblogs.com/chenpython123/p/11052276.html
(反引号)都是用来作命令替换的。命令替换与变量替换差不多,都是用来重组命令行的,先完成引号里的命令行,然后将其结果替换出来,再重组成新的命令行。
$( )与``在操作上,这两者都是达到相应的效果
运用:for循环打印下面这句话中字母数不大于6的单词
I am oldboy teacher welcome to oldboy training class.
#!/bin/bash
chars="i am xcn teacher welcome to xcn training class"
for n in $chars
do
if [ ${#n} -le 6 ]
then
echo $n
fi
done
#*,##*,#*,##*,% *,%% *
**,配合echo一般情况下,$var与${var}
是没有区别的,但是用${ }会比较精确的界定变量名称的范围。
[root@localhost ~]# A=Linux
[root@localhost ~]# echo $AB #表示变量AB
[root@localhost ~]# echo ${A}B #表示变量A后连接着B
LinuxB
连接两个字符串
V1="Hello"
V2="World"
V3=${V1}${V2}
echo $V3
输出:HelloWorld
截取变量的部分
file=/dir1/dir2/dir3/my.file.txt
可以用${ }分别替换得到不同的值:
${file#*/}: 删掉第一个 / 及其左边的字符串:dir1/dir2/dir3/my.file.txt
${file##*/}: 删掉最后一个 / 及其左边的字符串:my.file.txt
${file#*.}: 删掉第一个 . 及其左边的字符串:file.txt
${file##*.}: 删掉最后一个 . 及其左边的字符串:txt
${file%/*}: 删掉最后一个 / 及其右边的字符串:/dir1/dir2/dir3
${file%%/*}: 删掉第一个 / 及其右边的字符串:(空值)
${file%.*}: 删掉最后一个 . 及其右边的字符串:/dir1/dir2/dir3/my.file
${file%%.*}: 删掉第一个 . 及其右边的字符串:/dir1/dir2/dir3/my
记忆的方法为:
# 是 去掉左边(键盘上#在 $ 的左边)
%是去掉右边(键盘上% 在$ 的右边)
单一符号是最小匹配;两个符号是最大匹配
取子串及替换
命令 解释 结果
${file:0:5} 提取最左边的 5 个字节 /dir1
${file:5:5} 提取第 5 个字节右边的连续 5 个字节 /dir2
${file/dir/path} 将第一个 dir 提换为 path /path1/dir2/dir3/my.file.txt
${file//dir/path} 将全部 dir 提换为 path /path1/path2/path3/my.file.txt
${#file} 获取变量长度 27
$ (())中的Shell变量取值将转换成整数, 可以 整数运算、进制转换、重定义变量值
符号 | 功能 |
---|---|
+ - * / | 分别为加、减、乘、除 |
% | 余数运算 |
& |^ ! | 分别为“AND、OR、XOR、NOT” |
[root@localhost ~]# echo $((2*3))
6
[root@localhost ~]# a=5;b=7;c=2
[root@localhost ~]# echo $((a+b*c))
19
[root@localhost ~]# echo $(($a+$b*$c))
19
$(( ))可以将其他进制转成十进制数显示出来。用法如下:
echo $((N#xx))
其中,N为进制,xx为该进制下某个数值,命令执行后可以得到该进制数转成十进制后的值。
[root@localhost ~]# echo $((2#110))
6
[root@localhost ~]# echo $((16#2a))
42
[root@localhost ~]# echo $((8#11))
9
(( ))重定义变量值,是 [] 数学表达式的加强版
[root@localhost ~]# a=5;b=7
[root@localhost ~]# ((a++))
[root@localhost ~]# echo $a
6
[root@localhost ~]# ((a--));echo $a
5
[root@localhost ~]# ((a
0
[root@localhost ~]# ((a>b));echo $?
1
在linux的shell里,${name}可以表示变量,也可以表示数组。
name后面加〔〕的,一般是数组,
${name[*]} 是数组所有元素(all of the elements)
${name[@]} 是数组每一个元素(each of the elements) ,循环数组用这个 。
${#name[*]} 是数组元素的个数,也可以写成 ${#name[@]}
${name:-Hello} 是指,如果${name}没有赋值,那么它等于Hello,如果赋值了,就保持原值,不用管问这个Hello了。
${!array_name[@]} 、${!array_name[*]} 获取数组的下标。
str=" 114.114.114.114 2000:192:434:234 "
#变成数组
ip_list=(${str})
for i in "${!ip_list[@]}"; do
echo "@""$i=>${ip_list[i]}""@"
done
echo "数组个数: ${#ip_list[@]}"
echo "数组下标: ${!ip_list[@]}"
命令组。括号中的命令将会新开一个子shell顺序执行,所以括号中的变量不能够被脚本余下的部分使用。括号中多个命令之间用分号隔开,最后一个命令可以没有分号,各命令和括号之间不必有空格。
命令替换。等同于cmd
,shell扫描一遍命令行,发现了 ( c m d ) 结 构 , 便 将 (cmd)结构,便将 (cmd)结构,便将(cmd)中的cmd执行一次,得到其标准输出,再将此输出放到原来命令。有些shell不支持,如tcsh。
用于初始化数组。如:array=(a b c d) 【($str) 会把字符串按照 字段分隔符:空格、制表符、换行符 ,分割形成 数组】
获取文件的最后一行
cat test.txt | awk 'END {print}'
head test.txt | tail -1
tail -1 test.txt
打印10 行,而无需使用尾部和头部命令。
sed "10p" test.txt
打印第十行
head -10 test.txt | tail -1 # 当文件只有9行的时候这个解法默认也会输出最后一行
正确解法:
解法一:tail
tail -n +10 filename 从第10行输出
解法二:sed
sed -n '10p' filename 打印第10行内容
解法三:awk
cat file.txt | awk 'NR==10'
awk中NR和FNR
awk可以使用自身变量NR和FNR来处理多个文件。 NR:表示awk开始执行程序后所读取的数据行数。
FNR:awk当前读取的记录数,其变量值小于等于NR(比如当读取第二个文件时,FNR是从0开始重新计数,而NR不会)。
NR==FNR:用于在读取两个或两个以上的文件时,判断是不是在读取第一个文件
我们可以创建一个目录,为组中的每个人提供读取和执行访问权限,并将其粘滞位设置为"t”,如下所示
mkdir direc1
chmod g + wx direc1
chmod + t direc1
1、从本地复制到远程
scp local_file remote_username@remote_ip:remote_folder
或者
scp local_file remote_username@remote_ip:remote_file
或者
scp local_file remote_ip:remote_folder
或者
scp local_file remote_ip:remote_file
第1,2个指定了用户名,命令执行后需要再输入密码,第1个仅指定了远程的目录,文件名字不变,第2个指定了文件名;
第3,4个没有指定用户名,命令执行后需要输入用户名和密码,第3个仅指定了远程的目录,文件名字不变,第4个指定了文件名;
应用实例:
scp /home/space/music/1.mp3 [email protected]:/home/root/others/music
scp /home/space/music/1.mp3 [email protected]:/home/root/others/music/001.mp3
scp /home/space/music/1.mp3 www.runoob.com:/home/root/others/music
scp /home/space/music/1.mp3 www.runoob.com:/home/root/others/music/001.mp3
复制目录命令格式:
scp -r local_folder remote_username@remote_ip:remote_folder
或者
scp -r local_folder remote_ip:remote_folder
第1个指定了用户名,命令执行后需要再输入密码;
第2个没有指定用户名,命令执行后需要输入用户名和密码;
应用实例:
scp -r /home/space/music/ [email protected]:/home/root/others/
scp -r /home/space/music/ www.runoob.com:/home/root/others/
上面命令将本地 music 目录复制到远程 others 目录下。
2、从远程复制到本地
从远程复制到本地,只要将从本地复制到远程的命令的后2个参数调换顺序即可,如下实例
应用实例:
scp [email protected]:/home/root/others/music /home/space/music/1.mp3
scp -r www.runoob.com:/home/root/others/ /home/space/music/
说明
1.如果远程服务器防火墙有为scp命令设置了指定的端口,我们需要使用 -P 参数来设置命令的端口号,命令格式如下:
#scp 命令使用端口号 4588
scp -P 4588 [email protected]:/usr/local/sin.sh /home/administrator
2.使用scp命令要确保使用的用户具有可读取远程服务器相应文件的权限,否则scp命令是无法起作用的。
两个整数相加
方法 1
V1=1
V2=2
let V3=$V1+$V2
echo $V3
A=5
B=6
echo $(($A+$B)) # 方法 2
echo $[$A+$B] # 方法 3
expr $A + $B # 方法 4
echo $A+$B | bc # 方法 5
awk 'BEGIN{print '"$A"'+'"$B"'}' # 方法 6
定义数组
array=("Hi" "my" "name" "is")
打印数组的第一个元素
echo ${array[0]}
输出所有数组索引
echo ${!array[@]}
移除数组中索引为 2 的元素
unset array[2]
在数组中添加 id 为 333 的元素
array[333]="New_element"
Shell 练习题(四) 下期再见
个人标记:shell.docx 和 119