Linux下查找文件的一些应用场景

在实际应用中,我们经常会遇到各种查找文件的需求,比如:
查找最新的n个文件
查找包含某字符串的文件
查找昨天修改的文件
查找同级目录下,不同文件的最新一个文件(类似于数据库的分组查询场景:按名称分组,查询最新的文件)
等等
有木有?
 
 
下面是一些应用场景:
 
 
1、查找最近修改的文件
1)最近24小时内修改的文件
[sam@strong shelltest]$ find /opt/shell/tomcat-6.0.37/logs -mtime 0 -type f
/opt/shell/tomcat-6.0.37/logs/catalina.out
/opt/shell/tomcat-6.0.37/logs/runninglog/visit/warn.log.1
/opt/shell/tomcat-6.0.37/logs/runninglog/visit/warn.log
 
2)最近48~24小时内修改的文件
[sam@strong logs]$ find ./ -maxdepth 1 -mtime 1 -type f
./manager.2014-04-11.log
./catalina.2014-04-11.log
./host-manager.2014-04-11.log
./localhost.2014-04-11.log
 
3)最新的5个文件
[sam@strong shelltest]$ ls -tr /opt/shell/tomcat-6.0.37/logs/|tail -n 5
localhost.2014-04-11.log
catalina.2014-04-11.log
a2014-02-20.log$
ba2014-02-20.log.sdf
catalina.out
 
说明:
-mtime:最近第n个24小时内修改过的文件,0表示最近24小时内修改过的文件,1表示最近48~24小时内修改过的文件,以此类推
-maxdepth:指定查询目录的层级,1表示仅查找指定目录下的文件,不查询子目录,2表示查询指定目录及下一级目录,以此类推
-type:指定过滤文件类型,f表示普通文件
ls -tr:t表示按时间排序,一般默认为降序排序,r表示反序,所以最后文件的显示顺序为按时间升序显示
tail -n 5:表示只显示最后5行记录 ,不带参数时,默认显示前10行
 
2、按文件大小查找文件
1)从当前目录查找最大的3个文件
[sam@strong logs]$ ls -S|head -n 3
catalina.out
catalina.tar.gz
catalina.out.20140227
 
2)从当前目录查找最大的9个文件
[sam@strong logs]$ ls -lS|head
总计 95068
-rw-rw-r– 1 sam sam 73159998 04-12 23:41 catalina.out
-rw-rw-r– 1 sam sam 9300994 02-13 15:40 catalina.tar.gz
-rw-rw-r– 1 sam sam 4234391 02-27 11:14 catalina.out.20140227
-rw-rw-r– 1 sam sam 4054370 03-24 16:25 catalina.2014-03-24.log
-rw-rw-r– 1 sam sam 1923550 03-28 14:23 catalina.out.tar.gz
-rw-rw-r– 1 sam sam 568196 02-27 17:57 catalina.2014-02-27.log
-rw-rw-r– 1 sam sam 517827 03-21 14:51 catalina.2014-03-21.log
-rw-rw-r– 1 sam sam 421855 03-05 18:25 catalina.2014-03-05.log
-rw-rw-r– 1 sam sam 352904 02-28 17:08 catalina.2014-02-28.log
 
说明:
-S:表示按文件大小排序,一般默认为降序排序
head:不带参数时,默认显示前10行
 
3、按文件名称查找文件
1)查找当前目录中以2014-02-20.log为后缀的文件
只显示文件名
[sam@strong logs]ls|grep 2014-02-20.log
host-manager.2014-02-20.log
localhost.2014-02-20.log
manager.2014-02-20.log
 
显示文件绝对路径
[sam@strong logs]ls|grep 2014-02-20.log|sed “s:^:`pwd`/:”
/opt/shell/tomcat-6.0.37/logs/host-manager.2014-02-20.log
/opt/shell/tomcat-6.0.37/logs/localhost.2014-02-20.log
/opt/shell/tomcat-6.0.37/logs/manager.2014-02-20.log
 
说明:
其中用到了两个正则表达式的关键字
^ 表示一行的开头。sed “s:^:`pwd`/:”,表示在行头插入`pwd`/,`pwd`会转换为在当前目录执行pwd命令的结果
$ 表示一行的结尾。grep 2014-02-20.log$,表示过滤出以2014-02-20.log为后缀的文件
 
2)在shelltest目录中查找查找以f开头,以.sh结尾的文件
[sam@strong ~]$ find shelltest/ -name f\* .sh
shelltest/func.sh
shelltest/forwhileuntilcase.sh
 
4、按文件内容查找文件
查找当前目录中,出现字符串then的文件
[sam@strong shelltest]ls -l|grep ^[^d]|awk ‘NR!=1 {print8}’|xargs grep then
compute.sh:if [ x =y ]; then
compute.sh:then
compute.sh:if [ -f hello.sh ]; then
forwhileuntilcase.sh:echo “Hit a key, then hit return.”
inoutput.sh:then
[sam@strong shelltest]ls -l|grep ^[^d]|awk ‘NR!=1 {print8}’|xargs grep then|awk -F: ‘{print $1}’|uniq
compute.sh
forwhileuntilcase.sh
inoutput.sh
 
[sam@strong shelltest]ls –file-type|grep -v /|xargs grep then
compute.sh:if [ x =y ]; then
compute.sh:then
compute.sh:if [ -f hello.sh ]; then
forwhileuntilcase.sh:echo “Hit a key, then hit return.”
inoutput.sh:then
[sam@strong shelltest]ls –file-type|grep -v /|xargs grep then|awk ‘BEGIN{FS=”:”} {print $1}’|uniq
compute.sh
forwhileuntilcase.sh
inoutput.sh
 
说明:
以上两种方式的主要区别在于如何过滤掉目录,因为我们要查找的是文件。事实上,即使不过滤目录,查找的结果也是一致的。
ls -l之后,每行的第一个字母代表文件类型,d表示目录,正则表达式^[^d]表示只处理以非d开头的行
ls –file-type:执行之后目录会以/结尾,grep -v /$:忽略以/结尾的目录
awk ‘NR!=1 {print 8}’:NR!=1表示忽略第1行(因为执行ls -l之后,第1行显示多了一个总计信息),{print8}表示打印出第8列(即文件名,英文环境ls -l之后可能文件名是第9列)
awk -F: ‘{print $1}’:-F:表示以:为分隔符(作用与BEGIN{FS=”:”}相同),awk默认以空字符串为分隔符
xargs:从管道或标准输入读取数据,该数据可以作为后续命令的参数进行执行
uniq:重复的文件名只显示1个(此处不需要先进行sort排序,因为重复的文件名都是紧挨在一起的,相当于已经按文件名排好序了)
 
5、分组查找文件
假设有以下文件,查找出文件名以时间结尾的各类文件的最新一个文件
[sam@strong diffiles]$ ls -l
总计 0
-rw-rw-r– 1 sam sam 0 04-13 00:14 a_sub_20140410213155
-rw-rw-r– 1 sam sam 0 04-13 00:14 a_sub_20140411100530
-rw-rw-r– 1 sam sam 0 04-13 00:14 a_sub_20140412123011
-rw-rw-r– 1 sam sam 0 04-13 00:14 b_sub_20140410213155
-rw-rw-r– 1 sam sam 0 04-13 00:14 b_sub_20140411100530
-rw-rw-r– 1 sam sam 0 04-13 00:14 b_sub_20140412123011
-rw-rw-r– 1 sam sam 0 04-13 00:14 c_sub_20140410213155
-rw-rw-r– 1 sam sam 0 04-13 00:14 c_sub_20140411100530
-rw-rw-r– 1 sam sam 0 04-13 00:14 c_sub_20140412123011
-rw-rw-r– 1 sam sam 0 04-13 00:17 notme
 
[sam@strong diffiles]ls -l|awk ‘{print8}’|grep _sub_|awk -F_sub_ ‘{if (!filename[1] || filename[1]<2) filename[1]=$2;} END{for (i in filename) printf “%s_sub_%s\n”,i,filename[i]}’
a_sub_20140412123011
b_sub_20140412123011
c_sub_20140412123011
 
说明:
-F_sub_:以_sub_为分隔符,将文件名前后分为3部分
{if (!filename[1] || filename[1]<2) filename[1]=$2;}:使用数据,以文件名前缀为下标,时间为值,每次处理时保存同类文件的最大时间
END{for (i in filename) printf “%s_sub_%s\n”,i,filename[i]}:遍历分组后的数组,打印出文件名
 
最后,关于ls -l第一行的总计信息
假设当前目录如下
[sam@strong test]$ pwd
/home/sam/test
 
使用df命令查看目标文件所在的文件系统
[root@strong ~]# df -h
Filesystem Size Used Avail Use% Mounted on
/dev/mapper/VolGroup00-LogVol00 28G 8.1G 18G 32% /
/dev/vda1 99M 13M 82M 14% /boot
tmpfs 7.9G 0 7.9G 0% /dev/shm
则对应文件系统为:/dev/mapper/VolGroup00-LogVol00
 
使用root用户查看块大小
[root@strong ~]# tune2fs -l /dev/mapper/VolGroup00-LogVol00 | grep “Block size” 
Block size: 4096
 
ls -l查看总计信息
[nagios@strong test]$ ls -l 
total 52
-rw-rw-r– 1 sam sam 1723 Apr 12 23:27 local_lat.java
-rw-rw-r– 1 sam sam 2278 Apr 12 23:27 local_thr.java
-rw-rw-r– 1 sam sam 10113 Apr 12 23:27 Makefile
-rw-rw-r– 1 sam sam 512 Apr 12 23:27 Makefile.am
-rw-rw-r– 1 sam sam 9912 Apr 12 23:27 Makefile.in
-rw-rw-r– 1 sam sam 1853 Apr 12 23:27 remote_lat.class
-rw-rw-r– 1 sam sam 2049 Apr 12 23:27 remote_lat.java
-rw-rw-r– 1 sam sam 1224 Apr 12 23:27 remote_thr.class
-rw-rw-r– 1 sam sam 1722 Apr 12 23:27 remote_thr.java
 
因为块大小为4096bytes,即4k,Linux分配空间的时候,会以4096的整数倍为文件或目录进行分配,那么上面的计算公式为:
(1+1+3+1+3+1+1+1+1)*4=52K
 
 
好了,就这么多吧,如果大家还有其他使用场景或建议,欢迎共同探讨!
 
awk、sed参考资料:

---转载本站文章请注明作者和出处 二进制之路(binarylife.icu),请勿用于任何商业用途---

留下评论