前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >《调教命令行05》对文件的基本操作

《调教命令行05》对文件的基本操作

作者头像
xjjdog
发布2020-03-26 09:56:20
5560
发布2020-03-26 09:56:20
举报
文章被收录于专栏:架构专题
原创:小姐姐味道(微信公众号ID:xjjdog),欢迎分享,转载请保留出处。任何不保留此声明的转载都是抄袭。

接上文。 最近xjjdog的状态很差。也许是春天到了,也许是万物相互有感应的结果,小王的状态也很差。是我影响了他,让他在这个虚拟的世界里不断的yy又不断的沉沦。在此,xjjdog向这个虚拟的小王说一声:对不起,是我没有赋予你一马平川的能力,让你演了5集像韩剧一样又臭又长的电视剧。

但毕竟这种又臭又长是一种格调 ,小王决定认真的研究这个妹子,就如同他当年认真的研究Linux的命令一样。如果妹子是一张白纸,他会在上面书写什么呢?如果不是,他又能修改什么呢?但首先,他需要拿起笔。

你可能已经了解到,ll -l命令的第一列,能够显示linux的文件类型。请对此有一个大体的印象,因为后面的很多命令,会用到这些知识。

  • - 表示普通文件
  • d 表示目录文件
  • l 表示链接文件,比如快捷方式
  • s 套接字文件
  • c 字符设备文件,比如/dev/中的很多文件
  • b 表示块设备文件,比如一些磁盘
  • p 管道文件

Linux上的文件可以没有后缀,而且可以创建一些违背直觉的文件。比如后缀是png,但它却是一个压缩文件(通常不会这么做)。大学时,就有聪明的同学这样藏小电影,效果很好。

查看文件的具体类型,可以使用file命令,它很聪明,能够识别很多文件格式。

代码语言:javascript
复制
[root@localhost ~]# file /etc
/etc: directory
[root@localhost ~]# file /etc/group
/etc/group: ASCII text
[root@localhost ~]# file /dev/log
/dev/log: socket
[root@localhost ~]# file /dev/log
/dev/log: socket
[root@localhost ~]# file /bin
/bin: symbolic link to `usr/bin'

本小节的操作,面向的就是ASCII text类型的,普通文本文件。接下来,我们要创建一些文件。然后写入一些内容到文件里,以便进行后续的操作。

1、创建一个文件

1.1、数字序列

使用重定向符,能够直接生成文件。下面,我要生成10到20的数字,每一个数字单独一行,写入一个叫做spring的文件。巧的很,seq命令可以完成这个过程。

代码语言:javascript
复制
seq 10 20 >> spring

我们在前面提到过>的意思,是将前面命令的输出,重定向到其他地方。在这里,我们用了两个>,它依然是重定向的意思,但表示的是,在原来文件的基础上,追加内容。

也就是编程语言里的w+a+的意思

1.2、查看内容

为了查看文件的生成效果,可以使用cat命令检测。cat命令将会把文件的内容,输出打印到终端上。如果加上参数n,甚至可以打印行号。效果如下:

代码语言:javascript
复制
[root@localhost ~]# cat spring
10
11
12
13
14
15
16
17
18
19
20
[root@localhost ~]# cat -n spring
1    10
2    11
3    12
4    13
5    14
6    15
7    16
8    17
9    18
10    19
11    20

除了查看文件内容,cat命令通常用在更多的地方。只有和其他命令联合起来,它才会觉得生活有意义。

代码语言:javascript
复制
# 合并a文件和b文件到c文件
cat a  b>> c

# 把a文件的内容作为输入,使用管道处理。我们在后面介绍
cat a | cmd

# 写入内容到指定文件。在shell脚本中非常常用。我们在后面会多次用到这种写法
cat > index.html <<EOF
<html>
    <head><title></title></head>
    <body></body>
</html>
EOF

由于我们的文件不大,cat命令没有什么危害。但假如文件有几个GB,使用cat就危险的多,这只叫做的小命令,会在终端上疯狂的进行输出,你可以通过多次按ctrl+c来终止它。

2、平和的查看文件

既然cat命令不适合操作大文件,那一定有替换的方案。less和more就是。由于less的加载速度比more快一些,所以现在一般都使用less。它最主要的用途,是用来分页浏览文件内容,并提供一些快速查找的方式。less是一个交互式的命令,你需要使用一些快捷键来控制它。

这次我们使用seq生成一千万行记录,足足有76MB大小,然后用less打开它。

代码语言:javascript
复制
[root@localhost ~]# seq 10000000 > spring
[root@localhost ~]# du -h spring
76M    spring
[root@localhost ~]# less spring

关于less,一般操作如下:

  • 空格 向下滚屏翻页
  • b 向上滚屏翻页
  • / 进入查找模式,比如/1111将查找1111字样
  • q 退出less
  • g 到开头
  • G 去结尾
  • j 向下滚动
  • k 向上滚动,这两个按键和vim的作用非常像

3、文件头尾

head可以显示文件头,tail可以显示文件尾。它们都可以通过参数-n,来指定相应的行数。

代码语言:javascript
复制
[root@localhost ~]# head -n 3 spring
1
2
3
[root@localhost ~]# tail -n 3 spring
9999998
9999999
10000000

对于部分程序员来说,tail -f或许是最常用的命令之一。它可以在控制终端,实时监控文件的变化,来看一些滚动日志。比如查看nginx或者tomcat日志等等。通常情况下,日志滚动的过快,依然会造成一些困扰,需要配合grep命令达到过滤效果。

代码语言:javascript
复制
# 滚动查看系统日志
tail -f /var/log/messages

# 滚动查看包含info字样的日志信息
tail -f /var/log/messages | grep info

对于tail命令来说,还有一个大写的参数F。这个参数,能够监控到重新创建的文件。比如像一些log4j等日志是按天滚动的,tail -f无法监控到这种变化。

4、查找文件

考虑下面这个场景。我们需要找一个叫做decorator.py的文件,这个文件是个幽灵,可能存在于系统的任何地方。find命令,能够胜任这次捉鬼行动。

我们使用find命令,从根目录找起,由于系统的文件过多,下面的命令可能会花费一段时间。

代码语言:javascript
复制
[root@localhost site-packages]# find / -name decorator.py  -type f
/usr/lib/python2.7/site-packages/decorator.py

使用time命令,可以看到具体的执行时间。执行还是挺快的么!秒出!

代码语言:javascript
复制
[root@localhost site-packages]# time find / -name decorator.py  -type f
/usr/lib/python2.7/site-packages/decorator.py

real    0m0.228s
user    0m0.098s
sys    0m0.111s

find命令会查出一个路径的集合。通常是查询出来之后,进行额外的处理操作,一般配合xargs命令使用(xargs读取输入,然后逐行处理),至于find的exec参数?忘了它吧,不好用!

代码语言:javascript
复制
# 删除当前目录中的所有class文件
find . | grep .class$ | xargs rm -rvf

# 找到/root下一天前访问的文件,type后面的类型参见文章开头
find /root  -atime 1 -type f

# 查找10分钟内更新过的文件
find /root  -cmin  -10

# 找到归属于root用户的文件
find /root -user root

# 找到大于1MB的文件,进行清理
find /root -size  +1024k  -type f | xargs rm -f

find的参数非常非常多,记不住怎么办?除了常用的,其实都可以通过man命令查看。man的操作也和vi非常的类似,输入/EXAMPLES,会看到很多样例。不过我觉得还是上面列出的这些命令更加的适用。

4.1、数据来源

在上图中,你会看到mtime,ctime,atime类似的字样,它们的数据来自于何处呢?接下来我们顺理成章的看一下stat命令。

代码语言:javascript
复制
[root@localhost ~]# stat spring
  File: ‘spring’
  Size: 78888897      Blocks: 154080     IO Block: 4096   regular file
Device: fd00h/64768d    Inode: 8409203     Links: 1
Access: (0644/-rw-r--r--)  Uid: (    0/    root)   Gid: (    0/    root)
Context: unconfined_u:object_r:admin_home_t:s0
Access: 2019-11-04 18:01:46.698635718 -0500
Modify: 2019-11-04 17:59:38.823458157 -0500
Change: 2019-11-04 17:59:38.823458157 -0500
 Birth: -

这不就是文件属性么?从文件大小,到文件类型,甚至到最后修改、访问时间,都可以从这里获取。Linux文件系统以块为单位存储信息,为了找到某一个文件所在存储空间的位置,会用i节点(inode) 对每个文件进行索引,你可以认为它是一个文件指针。

  • 文件的字节数
  • 文件拥有者user
  • 文件所属组group
  • 文件的读、写、执行权限
  • 文件的时间戳
    • ctime指inode上一次变动的时间
    • mtime指文件内容上一次变动的时间
    • atime指文件上一次打开的时间。
  • 链接数,即有多少文件名指向这个inode (ln命令)
  • 文件数据block的位置(具体的数据位置)

关于inode是一个比较大的话题,也是比较重要的知识点,有兴趣的可以自行搜索。我们只需要知道这些信息是从这里来的就可以了。

4.2、小练习

如果我只想获取Modify这个数值,可以组合使用一下上面学到的命令。首先获取最后三行,然后获取首行。效果如下:

代码语言:javascript
复制
[root@localhost ~]# stat spring | tail -n 3 | head -n 1
Modify: 2019-11-04 17:59:38.823458157 -0500

下面几个命令,效果是与上面等价的,输出结果也是一模一样。正所谓条条大路通罗马,接下来,我们首先介绍一下出现频率较高的grep。另外,我们在上面的这些命令中,多次使用了|,这是Linux中非常重要的管道概念,下面也会着重介绍。

代码语言:javascript
复制
stat spring | head -n 7 | tail -n 1
stat spring | grep Modify
stat spring | sed -n '7p'
stat spring | awk 'NR==7'

5、字符串匹配

grep用来对内容进行过滤,带上--color参数,可以在支持的终端可以打印彩色,参数n则用来输出具体的行数,用来快速定位。这是一个必须要熟练使用的命令。

比如:查看nginx日志中的POST请求。

代码语言:javascript
复制
grep -rn --color POST access.log

推荐每次都使用这样的参数。

如果我想要看某个异常前后相关的内容,就可以使用ABC参数。它们是几个单词的缩写,经常被使用。

  • A after 内容后n行
  • B before 内容前n行
  • C 内容前后n行

就像是这样:

代码语言:javascript
复制
# 查看Exception关键字的前2行和后10行
grep -rn --color Exception -A10 -B2   error.log

#查找/usr/下所有import关键字,已经它们所在的文件和行数
grep -rn --color import /usr/

6、管道

在上面的命令中,我们多次用到了|,这貌似可以完成一些神奇的事情。|pipe的意思,它可以把多个命令联系起来。通常,命令有下面的关联方式:

  • ; 顺序执行,如mkdir a;rmdir a
  • && 条件执行,如mkdir a && rmdir a
  • || 条件执行,如mkdir a || rmdir a,后面的命令将不执行
  • | 管道,前面命令的输出,将作为后面命令的输入

前三种的命令关联,是非常简单有逻辑的,非常的好理解。而管道,却有自己的特点。

接触过编程语言的都知道stdinstdoutstderr的概念。让我们重新组织一下针对于管道的定义:前面命令的输出(stdin),将作为后面命令的输入(stdout)。

我们拿一行命令来说明。

代码语言:javascript
复制
seq 20 100 | head -n 50 | tail -n 1

上面命令,将输出69。69是个神奇的数字,它是怎么办到的呢?我们来一张小图,一切就豁然开朗了。

关于输入输出和错误,linux使用一个数字进行缩写,这在一些脚本中,甚至在一些安装文件中,会经常用到。

  • 0 表示stdin标准输入
  • 1 表示stdout标准输出
  • 2 表示stderr标准错误

通过类似2>&1的语法,可以把错误信息定向到标准输出。我们用命令来证明一下。

代码语言:javascript
复制
# 错误信息无法输出到文件
[root@localhost ~]# cat aaaaaaaaa > b
cat: aaaaaaaaa: No such file or directory
[root@localhost ~]# cat b

# 错误信息被重定向了
[root@localhost ~]# cat aaaaaaaaa > b 2>&1
[root@localhost ~]# cat b
cat: aaaaaaaaa: No such file or directory

7、排序

在了解管道的工作原理之后,就可以介绍一下sort命令了。它通常可以和uniq(去重)命令联合,完成一些排序、去重的操作。首先使用cat命令,生成如下内容的文件。

代码语言:javascript
复制
cat > sort.txt <<EOF
1 11
3 22
2 44
4 33
5 55
6 66
6 66
EOF

接下来让这两个命令上台表演一下。sort可以使用-t指定分隔符,使用-k指定要排序的列。但是空格,是不需要做这些画蛇添足的指定的。

代码语言:javascript
复制
# 根据第一列倒序排序
[root@localhost ~]# cat sort.txt | sort  -n -k1 -r
6 66
6 66
5 55
4 33
3 22
2 44
1 11

# 统计每一行出现的次数,并根据出现次数倒序排序
# 此时,行数由7变成了6
[root@localhost ~]# cat sort.txt | sort  | uniq -c  | sort -n -k1 -r
2 6 66
1 5 55
1 4 33
1 3 22
1 2 44
1 1 11

注意:uniq命令,一般用在已经经过排序的结果集上。所以,很多情况需要首先使用sort命令进行排序后,再使用uniq命令。新手经常会忘记第一步,造成命令不能正常运行。

8、小结

本小节,我们从文件的属性开始说起,了解了几个对文件操作的常用命令。并顺便介绍了管道的概念。下面,我们来练习一下。

找到系统中所有的grub.cfg文件,并输出它的行数。

分析:首先需要使用find命令,找到这些文件。然后使用xargs逐行处理。最后,使用wc命令,统计确切的行数。

代码语言:javascript
复制
[root@localhost grub2]# find / | grep grub.cfg | xargs wc -l
141 /boot/grub2/grub.cfg

输出系统的group列表

代码语言:javascript
复制
cat /etc/group | awk -F ':' '{print $1}'

下面这个命令输出nginx日志的ip和每个ip的pv,pv最高的前10

代码语言:javascript
复制
# 2019-06-26T10:01:57+08:00|nginx001.server.ops.pro.dc|100.116.222.80|10.31.150.232:41021|0.014|0.011|0.000|200|200|273|-|/visit|sign=91CD1988CE8B313B8A0454A4BBE930DF|-|-|http|POST|112.4.238.213

awk -F"|" '{print $3}' access.log | sort | uniq -c | sort -nk1 -r | head -n10

9、思考&扩展

1、Linux的终端,是如何实现彩色的文字的?我要如何输出一个绿色的Hello World?

2、软链接与硬链接有什么区别?

3、了解几个偏门但又不是非常偏的命令。

  • cut 有了awk,几乎不怎么会用cut了
  • tr
  • col
  • paste
  • join
  • split

End

潮湿的眼神,忧郁的裤裆。

或许,保守才是小王最大的伤痛,是因也是果,是果躲不过。这种性格,一开始就决定了,到了30多岁,他还是孑然一身。

世事洞明皆学问,人情炼达即文章。下一小节,我将带小王了解:条条道路通罗马,铁树也能开出花。

作者简介:小姐姐味道 (xjjdog),一个不允许程序员走弯路的公众号。聚焦基础架构和Linux。十年架构,日百亿流量,与你探讨高并发世界,给你不一样的味道。我的个人微信xjjdog0,欢迎添加好友,进一步交流。

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2020-03-23,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 小姐姐味道 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 1、创建一个文件
    • 1.2、查看内容
    • 2、平和的查看文件
    • 3、文件头尾
    • 4、查找文件
      • 4.1、数据来源
        • 4.2、小练习
        • 5、字符串匹配
        • 6、管道
        • 7、排序
        • 8、小结
        • 9、思考&扩展
        • End
        领券
        问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档