linux shell攻略学习笔记二

1.Cat命令

 

这么多命令,常用的

Cat –n file  显示文件以及行数

Cat -

echo 'Text through stdin' | cat - file.txt

Text through stdin

this is file and test   #这个是file.txt的内容,就是echo打印出管道符接的stdin

 

2.录制并回放终端会话

利用script和scriptreplay命令

录制
$ script -t 2> timing.log -a output.session
type commands;
…
..
exit

两个配置文件被当做script命令的参数。其中一个文件(timing.log)用于存储时序信息,

描述每一个命令在何时运行;另一个文件(output.session)用于存储命令输出。

-t 选项用于将时序数据导入stderr。

2> 则用于将stderr重定向到timing.log。

 

回放

利用这两个文件:timing.log(存储时序信息)和output.session(存储命令输出信息),我们

可以按照下面的方法回放命令执行过程:

$ scriptreplay timing.log output.session
# 按播放命令序列输出

3.Find查找

1.用正则查找文件

–name  -iname(忽略大小写)
find /home/slynux -name "*.txt" –print
find . -iname "example*" -print
多个条件查找
find . \( -name "*.txt" -o -name "*.pdf" \) -print

按路径匹配

find /home/users -path "*/slynux/*" -print
直接用正则
find . -regex ".*\(\.py\|\.sh\)$"
find . -iregex ".*\(\.py\|\.sh\)$"

2.否定!

find . ! -name "*.txt" -print

3.于目录深度的搜索

find . -maxdepth 1 -name "f*" –print    #最大深度
find . -mindepth 2 -name "f*" –print          #最小深度

4.根据文件类型搜索

Unix类系统将一切都视为文件。文件具有不同的类型,例如普通文件、目录、字符设备、块

设备、符号链接、硬链接、套接字以及FIFO等。

find . -type d –print  #找目录
find . -type f –print  #找文件

5.根据文件时间进行搜索

这个感觉很少用到 单位是天

访问时间(-atime):用户最近一次访问文件的时间。
修改时间(-mtime):文件内容最后一次被修改的时间。
变化时间(-ctime):文件元数据(例如权限或所有权)最后一次改变的时间。

这些整数值通常还带有 - 或 + :- 表示小于,+ 表示大于。

打印出在最近7天内被访问过的所有文件:

find . -type f -atime -7 -print

打印出恰好在7天前被访问过的所有文件:

find . -type f -atime 7 -print

 

以分钟作为计量单位

-amin(访问时间);
-mmin(修改时间);
-cmin(变化时间)。

 

打印出访问时间超过7分钟的所有文件:

find . -type f -amin +7 -print

find另一个漂亮的特性是 -newer参数。使用 -newer,我们可以指定一个用于比较时间戳 的参考文件,然后找出比参考文件更新的(更近的修改时间)所有文件

找出比file.txt修改时间更近的所有文件

find . -type f -newer file.txt -print

6.基于文件大小的搜索

find . -type f -size +2k   #大于2KB的文件 小于2k用-  等于不用+-
除了k之外,还可以用其他文件大小单元。
 b —— 块(512字节)。
 c —— 字节。
 w —— 字(2字节)。
 k —— 1024字节。
 M —— 1024K字节。
 G —— 1024M字节。

7. 删除匹配的文件

删除当前目录下所有的 .swp文件:

 $ find . -type f -name "*.swp" -delete

8. 基于文件权限和所有权的匹配

find . -type f -perm 644 -print

# 打印出权限为644的文件

用途:找出那些没有设置好执行权限的PHP文件

9. 利用find执行命令或动作(厉害了)

find命令可以借助选项-exec与其他命名进行结合。

场景:用 -user找出root拥有的所有文件,然后用-exec更改所有权。

find . -type f -user root -exec chown slynux {} \;

在这个命令中,({}其实就是类似查找出的文件的引用)

{}是一个与 -exec选项搭配使用的特殊字符串。对于每一个匹配的文件,{}会被替换成相应的文件名。例如,find命令找到两个文件test1.txt和test2.txt,其所有者均为slynux,那么find就会执行:chown slynux {}

它会被解析为chown slynux test1.txt和chown slynux test2.txt。

\; 通过转义的分号结束

find . -type f -name "*.c" -exec cat {} \;>all_c_files.txt  #cat文件追加到all_file.txt

将10天前的 .txt文件复制到OLD目录中

find . -type f -mtime +10 -name "*.txt" -exec cp {} OLD \;

-exec结合多个命令

默认-exec执行的是单个命令,把多个命令写到一个shell脚本中(例如command.sh),然

后在-exec中使用这个脚本:

-exec ./commands.sh {} \;

Print0

find . -type f -name "*.a" -print
./a.a
./b.a

find . -type f -name "*.a" -print0
./a.a./b.a

4.xargs

xargs命令应该紧跟在管道操作符之后,以标准输入作为主要的源数据流。

command | xargs

样例文件

$ cat example.txt # 样例文件
1 2 3 4 5 6
7 8 9 10
11 12
转单行

这里默认定界符为$IFS (换行/制表符/空格)

$ cat example.txt | xargs
输出:1 2 3 4 5 6 7 8 9 10 11 12
转多行
$ cat example.txt | xargs -n 3
1 2 3
4 5 6
7 8 9
10 11 12
自定义定界符

通过参数 –d指定定界符

$ echo "splitXsplitXsplitXsplit" | xargs -d X
split split split split

 

-d –n可以一起用

$ echo "splitXsplitXsplitXsplit" | xargs -d X -n 2
split split
split split
一次传多个参数
--------样例sh脚本
#!/bin/bash
#文件名: cecho.sh
echo $*'#'

--------样例测试文件
$ cat args.txt
arg1
arg2
arg3

1.调用三次脚本

$ cat args.txt | xargs -n 1 ./cecho.sh
arg1 #
arg2 #
arg3 #

2.三个参数一次传入

$ cat args.txt | xargs ./cecho.sh
arg1 arg2 arg3 #

3.简化重复参数的脚本

./cecho.sh -p arg1 -l
./cecho.sh -p arg2 -l
./cecho.sh -p arg3 -l

简化后

$ cat args.txt | xargs -I {} ./cecho.sh -p {} -l
-p arg1 -l #
-p arg2 -l #
-p arg3 -l #

xargs有一个选项-I,可以提供上面这种形式的命令执行序列。我们可以用-I指定替换字符

串,这个字符串在xargs扩展时会被替换掉。如果将-I与xargs结合使用,对于每一个参数,命

令都会被执行一次。

-I {} 指定了替换字符串

xargs -0指定null为定界符

场景:xargs的输入和输出只能是stdin和stdout

很多文件名中都可能会包含空格符(' '),因此xargs 很可能会误认为它们是定界符(例如,hell text.txt会被xargs误解为hell和text.txt)就必须将 -print0与find结合使用,以字符null ('\0')来分隔输出。

用法:

只要我们把find的输出作为xargs的输入,就必须将 -print0与find结合使用,以字符null ('\0')也就是xargs -0来分隔输出。

find . -type f -name "*.a" -print | xargs  wc –l

优化后:

find . -type f -name "*.a" -print0 | xargs -0 wc -l

print0 是将查找结果“扁平化”放到一行,而xargs -0会用空格分割打印出各个文件。

find ./ -name "*.sh" -print0 |xargs -0
./test1.sh  ./test02.sh  ./testlog.sh  ./pass.sh  ./fun.sh

补充场景:

一个文件要根据不同参数,运行同一个脚本

$ cat args.txt
arg1
arg2
arg3

脚本内容:

#!/bin/bash
#文件名: cecho.sh
echo $*'#'

普通人调用:

./cecho.sh arg1
./cecho.sh arg2
./cecho.sh arg3

有了xargs后:

cat args.txt | xargs -n 1 ./cecho.sh
arg1 #
arg2 #
arg3 #

 

还有个厉害的

$ cat args.txt | xargs -I {} ./cecho.sh -p {} -l
-p arg1 -l #
-p arg2 -l #
-p arg3 -l #

其中 –p 变量  -l 里-p是不变的,-l也是不变的。

xargs有一个选项-I,可以提供上面这种形式的命令执行序列。我们可以用-I指定替换字符

串,这个字符串在xargs扩展时会被替换掉。如果将-I与xargs结合使用,对于每一个参数,命

令都会被执行一次。

 

还可以这样:

$ cat files.txt | ( while read arg; do cat $arg; done )
# 等同于cat files.txt | xargs -I {} cat {}

 

5.tr 转换

tr只能通过stdin(标准输入),而无法通过命令行参数来接受输入

tr [options] set1 set2

set1和set2代表集合 'A-Z' 和 'a-z'都是集合。

'ABD-}'、'aA.,'、'a-ce-x'以及'a-c0-9'等均是合法的集合。

 

就是替换set1的内容为ste2的内容,set1到set2是严格映射,如hashmap,set1是map的key,set2是map的val。

echo "HELLO WHO IS THIS" | tr 'A-Z' 'a-z'
用途1:加解密

$ echo 12345 | tr '0-9' '9876543210'

87654 # 已加密

$ echo 87654 | tr '9876543210' '0-9'

12345 # 已解密

 

用途2:删除字符

tr有一个选项-d,可以通过指定需要被删除的字符集合,

$ echo "Hello 123 world 456" | tr -d '0-9'

Hello world

# 将stdin中的数字删除并打印出来

 

补集-c

补集就是取反。

$ echo hello 1 char 2 next 4 | tr -d -c '0-9 \n'

 1 2 4

 

通途3:删除重复

Tr –s 删除重复  下面是删除重复的空格

$ echo "GNU is not UNIX. Recursive right ?" | tr -s ' '

GNU is not UNIX. Recursive right ?

 

其他关键字

比如小写换大写:

echo "hello word"|tr '[:lower:]' '[:upper:]'

HELLO WORD

 

6.校验和

用途:Src源有文件盒MD5文件,下载目标下载文件后,用下载的md5校验文件。

用途2:MD5用来判定2个文件是否是同一个文件。

 

Md5

$ md5sum filename

68b329da9893e34099c7d8ad5cb9c940 filename

 

$ md5sum file1 file2 file3 ..

当使用多个文件时,输出中会在每行中包含单个文件的校验和:

[checksum1] file1

[checksum1] file2

[checksum1] file3

 

校验

如果需要用所有的.md5信息来检查所有的文件,可以使用:

$ md5sum -c *.md5

 

SAH-1

Sha-1和MD5类似,注意2点

  1. 命令变为sha1sum
  2. .md5文件变为.sha1。如file_sum.md5改为file_sum.sha1

 

加密工具与散列

感觉没啥用,不写了。

md5sum和SHA-1已不再安全。因为计算能力 的攀升使其变得容易被破解。推荐使用bcrypt或sha512sum这 类工具进行加密

 

8.排序、唯一与重复

 

排序

sort命令既可以从特定的文件,也可以从stdin中获取输入,并将输出写入stdout。uniq 的工作方式和sort一样。

 

(2) -n按照数字顺序进行排序:

$ sort -n file.txt

(3) -r按照逆序进行排序:

$ sort -r file.txt

(4) 按照月份进行排序(依照一月,二月,三月……):

$ sort -M months.txt

(5) 合并两个已排序过的文件:

$ sort -m sorted1 sorted2

 

(6) -k指定了排序应该按照哪一个键(key)来进行。

样例文件

$ cat data.txt
1 mac 2000
2 winxp 4000
3 bsd 1000
4 linux 1000

# 依据第1列,以逆序形式排序

$ sort -nrk 1 data.txt
4 linux 1000
3 bsd 1000
2 winxp 4000
1 mac 2000
# -nr表明按照数字,采用逆序形式排序

# 依据第2列进行排序

$ sort -k 2 data.txt
3 bsd 1000
4 linux 1000
1 mac 2000
2 winxp 4000

 

指定多列排序

$ cat data.txt
1010hellothis
2189ababbba
7464dfddfdfd
$ sort -nk 2,3 data.txt

起止位置是2和3,就是group by sort 第二列和第三列;不需要做切割什么的了

uniq

uniq只能作用于排过序的数据输入,因此,uniq要么使用管道,要么将排过序的文件作为

输入,与sort命令结合使用。

样例文件

$ cat sorted.txt
bash
foss
hack
hack

去重

$ sort unsorted.txt | uniq

 

-u找出不重复,唯一的行。

$ sort unsorted.txt | uniq -u
bash
foss

-c显示重复次数

$ sort unsorted.txt | uniq -c
 1 bash
 1 foss
 2 hack

-d找出重复的行

$ sort unsorted.txt | uniq -d
hack

 

-s 指定可以跳过前n个字符;

-w 指定用于比较的最大字符数。

 

9.分割文件和

$ split -b 10k data.file -d -a 4

-b  除了k(KB)后缀,我们还可以使用M(MB)、G(GB)、c(byte)、w(word)等后缀

-d 以数字为后缀,可以另外使用-d参数

-a length可以指定后缀长度

-l,  --lines=NUMBER      put NUMBER lines per output file按行切割。

Csplit

$ cat server.log
SERVER-1
[connection] 192.168.0.1 success
[connection] 192.168.0.2 failed
[disconnect] 192.168.0.3 pending
[connection] 192.168.0.4 success
SERVER-2
[connection] 192.168.0.1 failed
[connection] 192.168.0.2 failed
[disconnect] 192.168.0.3 success
[connection] 192.168.0.4 failed
SERVER-3
[connection] 192.168.0.1 pending
[connection] 192.168.0.2 pending
[disconnect] 192.168.0.3 pending
[connection] 192.168.0.4 failed

我们需要将这个日志文件分割成server1.log、server2.log和server3.log,这些文件的内容分别

取自原文件中不同的SERVER部分。那么,可以使用下面的方法来实现:

$ csplit server.log /SERVER/ -n 2 -s {*} -f server -b "%02d.log" ; rm server00.log
$ ls
server01.log server02.log server03.log server.log

有关这个命令的详细说明如下。

  •  /SERVER/ 用来匹配某一行,分割过程即从此处开始。
  •  /[REGEX]/ 表示文本样式。包括从当前行(第一行)直到(但不包括)包含“SERVER”
  • 的匹配行。
  •  {*} 表示根据匹配重复执行分割,直到文件末尾为止。可以用{整数}的形式来指定分割执
  • 行的次数。
  •  -s 使命令进入静默模式,不打印其他信息。
  •  -n 指定分割后的文件名后缀的数字个数,例如01、02、03等。
  •  -f 指定分割后的文件名前缀(在上面的例子中,server就是前缀)。
  •  -b 指定后缀格式。例如%02d.log,类似于C语言中printf的参数格式。在这里文件名=前缀+后缀=server + %02d.log。

因为分割后的第一个文件没有任何内容(匹配的单词就位于文件的第一行中),所以我们删

除了server00.log。

根据扩展名切分文件名

借助%操作符可以轻松将名称部分从“名称.扩展名”这种格式中提取出来。你可以按照下面

的方法从sample.jpg中提取名称。

file_jpg="sample.jpg"
name=${file_jpg%.*}
echo File name is: $name

输出结果:

File name is: sample

下一个任务是将文件名的扩展名部分提取出来,这可以借助 # 操作符实现。

提取文件名中的 .jpg并存储到变量file_jpg中:

extension=${file_jpg#*.}
echo Extension is: jpg
#输出结果:
Extension is: jpg

10.交互输入自动化

echo –e实现

样例脚本

#!/bin/bash
#文件名: interactive.sh
read -p "Enter number:" no ;
read -p "Enter name:" name
echo You have entered $no, $name;
 
$ echo -e "1\nhello\n" | ./interactive.sh
You have entered 1, hello

我们用echo -e来生成输入序列,-e表明echo会解释转义序列

Expect实现

在默认情况下,多数常见的Linux发行版中并不包含expect

自动化脚本

#!/usr/bin/expect
#文件名: automate_expect.sh
spawn ./interactive.sh
expect "Enter number:"
send "1\n"
expect "Enter name:"
send "hello\n"
expect eof

运行结果如下:

$ ./automate_expect.sh

 

解释脚本:

Spawn      参数指定需要自动化哪一个命令;

Expect      参数提供需要等待的消息;

Send          是要发送的消息;

expect eof        指明命令交互结束。

 

11. &并行进程

我们利用了Bash的操作符&,它使得shell将命令置于后台并继续执行脚本。这意味着一旦循环结束,脚本就会退出,而md5sum命令仍在后台运行。

为了避免这种情况,我们使用$!来获得进程的PID,在Bash中,$!保存着最近一个后台进程的PID。我们将这些PID放入数组,然后使用wait命令等待这些进程结束。

posted @ 2019-12-20 23:00  Nucky_yang  阅读(388)  评论(0编辑  收藏  举报