6、系统文件查找与文件管理

发布时间 2023-10-27 20:47:01作者: old_bird

综所周知,一个linux系统是由很多文件组成的,那么既然有那么多文件,那我们该如何管理这些文件呢?

Linux中的所有数据都是以文件形式存在的,那么所有文件分别被归类到不同的文件系统中。而文件系统则是一种树型结构,通俗的理解为目录。

在linux系统中,你所做的每一步操作及所执行的每个命令都是基于文件系统底层逻辑来呈现出来的。

说到管理linux文件,首先您得先找见它!通过本节可以了解linux的文件管理第一步:查找文件等。今天这篇文章主要介绍下两个用来在linux系统中查找文件的工具或者命令程序。

• locate –通过名称来查找文件

• find – 在一个目录层次结构中搜索文件

locate - 查找文件的简单方法

locate 命令程序会执行一次快速的路径名数据库搜索进程,并且输出结果是与给定字符串相匹配的路径名称。locate 命令程序只能依据文件名来查找文件。

例如,找到所有名字以“zip”开头的文件:

[root@linuxprobe ~]$ locate bin/zip

locate 命令程序执行搜索路径名数据库进程,并输出任一个包含字符串“bin/zip”的路径名:

/usr/bin/zip

/usr/bin/zipgrep

/usr/bin/zipinfo

/usr/bin/zipsplit

或者结合其它命令工具,例如grep 命令,来执行更全面的搜索:

[root@linuxprobe ~]$ locate zip | grep bin

/bin/bunzip2

/bin/bzip2

/bin/gunzip

/bin/gzip

/usr/bin/funzip

/usr/bin/gpg-zip

/usr/bin/prezip

/usr/bin/prezip-bin

/usr/bin/unzip

/usr/bin/zip

/usr/bin/zipgrep

/usr/bin/zipinfo

/usr/bin/zipsplit

扩展知识:

有时候locate命令程序不能正常工作,但是呢第二天它就正常工作了。解决方法:首先转换为超级用户身份,在提示符下运行updatedb 命令,可以手动运行updatedb 命令程序即可。

目前,不同版本的Linux发行版中locate 命令程序有很多演变,不过它们都会拥有一定重叠的选项集合,可通过查看locate 命令的手册来确定安装了哪个版本的locate 命令程序。

find - 查找文件的高阶之路

find 命令程序支持基于给定的各种属性搜索查找文件。find 命令程序的魅力所在就是它能够找到符合特定标准属性的文件。

  1. 最简单的查找方式:

find 命令程序支持接收多个目录名来执行搜索查找。

例如:

[root@linuxprobe ~]$ find ~ //输出家目录的路径名列表

可想而知,查找结果会产生很大的列表。那我们可以尝试使用wc 命令程序来计算并显示出文件的数量:

[root@linuxprobe ~]$ find ~ | wc

-l46052

find 命令程序支持的常见文件类型测试条件如下:

表: find 文件类型

 

  1. 通过文件大小和文件名搜索查找

例如:

查找所有文件名匹配通配符模式“*.JPG”和文件大小大于1M 的普通文件:

[root@linuxprobe ~]$ find ~ -type f -name "*.JPG" -size +1M | wc -l

237

//引入-name 测试条件,后面跟通配符模式。

//双引号引起来的作用就是阻止shell 展开路径名进程。

//引入-size 测试条件,后跟字符串“+1M”。加号“+”代表正在寻找文件大小大于指定数的文件。若以减号“-”开头,那就代表查找小于指定数的文件。若没有符号意味着“精确匹配这个数”。字母“M”表明测量单位是兆字节。测量单位的指定如下表:

表: find 大小单位

 

以上列出的只是冰山一角,find 命令手册有更详细的说明。

总结:

find 命令程序搜索目录树以查找一个文件或一组文件。它遍历目录树并报告与用户规范匹配的文件的所有匹配项。查找程序包括非常强大的搜索功能。

locate 程序扫描一个或多个文件名数据库,并显示任何匹配项。如果文件在上次文件名数据库更新期间存在,则可以将其用作非常快速的查找命令。

当然,linux文件类型是不可或缺的一部分,在Linux中,基本的文件类型有以下三种:

1) 普通文件

普通文件基本包括文本文件、源码文件、可执行文件等。

2) 目录

目录可以包含普通文件和特殊文件,目录相当于Windows系统和Mac 系统中的文件夹。

3) 设备文件

设备文件就是Linux 与外部设备(如光驱,打印机等)进行通信所必需的文件。

 

Find命令所属操作列表中的条目,有助于我们想要的结果输出。

预定义操作描述:

 

例如:

find ~

find ~ -print

//此命令将home家目录中包含的每个文件和子目录输出。以一个列表的形式输出。两种命令的输出完全一致。

删除特定条件的文件

使用find 命令可以删除符合一定条件的文件。

例如:

find ~ -type f -name '*.BAK' -delete

//删除扩展名为“.BAK”(这通常用来指定备份文件)的文件, 在用户家目录及它的子目录下搜索以.BAK 结尾的文件名。一旦以.BAK 结尾的文件被找到后,就删除它们。

备注:当使用-delete 操作命令时,你肯定会格外小心。那我们怎么做更妥当呢?妥当的做法是我们可以先使用print程序命令测试下,是否符合我们要的搜索结果。

逻辑关系—逻辑运算符

例如:

find ~ -type f -and -name '*.BAK' -and -print

这个程序命令一旦被执行,它就会搜索以.BAK后缀的相关文件,并将符合条件文件的相对路径名称标准输出给我们。命令执行的原因是由每个测试和操作之间的逻辑关系决定的。

那么逻辑运算符是如何影响命令如何执行的呢?

 

此表可以看出测试和行为之间的逻辑关系决定了哪一个会被先执行,同时测试和行为的顺序也很重要。

我们重新调整下测试和行为之间的顺序:让-print 行为是第一个,那么结果会截然不同:

例如:

find ~ -print -and -type f -and -name '*.BAK'

上述命令会输出每个文件(-print 行为总是为真),然后才是测试文件类型和指定的文件扩展名。

用户定义操作

除了预定义的操作外,我们可以调用任意的命令。通常情况下是通过-exec 命令。

例如:

-exec command {} ;

command 代表一个命令的名字,{} 代表当前路径名的符号表示,分号代表必要的分隔符,表明命令的结束。

当然,如何交互式地执行一个用户定义的操作行为?通过使用-ok 操作来代替-exec,它在执行每个指定的命令之前,会提示用户:

find ~ -type f -name 'foo*' -ok ls -l '{}' ';'

< ls ... /home/me/bin/foo > ? y

-rwxr-xr-x 1 me me 224 2007-10-29 18:44 /home/me/bin/foo

< ls ... /home/me/foo.txt > ? y

-rw-r--r-- 1 me me 0 2008-09-19 12:53 /home/me/foo.txt

Xargs命令

xargs 命令的用法—将标准输入或管道构造的参数列表转换成某一特定命令的参数列表并运行该特定命令。通俗的来讲就是xargs取其中一个命令的输出结果作为另外一个命令的参数列表来执行。对于我们的例子,我们可以这样使用它:

find ~ -type f -name 'foo*' -print | xargs ls -l

-rwxr-xr-x 1 me me 224 2007-10-29 18:44 /home/me/bin/foo

-rw-r--r-- 1 me me 0 2008-09-19 12:53 /home/me/foo.txt

这里我们可以得到一个结论:

find命令的执行结果通过管道符|传递给xargs命令,然后,xargs命令将find命令的输出结果作为ls命令的参数,最后再执行ls -l命令。

备注:当某一命令行中的参数列表数量是有限制的,一旦超过linux系统支持的最大长度时,那么xargs命令将会执行该命令,然后一直重复这个过程直到耗尽标准输入。

接下来咱们再看下如何创建一个包含许多子目录和文件:

[root@linuxprobe~]$ mkdir -p playground/dir-{00{1..9},0{10..99},100}

[root@linuxprobe~]$ touch playground/dir-{00{1..9},0{10..99},100}/file-{A..Z}

Linux命令的强大功能真是令人惊叹啊!仅仅用了这两行命令,就可以创建一个包含一百个子目录,而且每个子目录中包含了26 个空文件。

现在咱们看看Linux命令是如何实现这个奇迹的!

一个简单的mkdir命令,一个特异的shell 扩展(花括号)包括一个touch命令。通过组合mkdir 命令和-p 参数选项(导致mkdir 命令创建指定路径的父目录),以及花括号,这样的话就能够创建一百个目录。

备注:touch命令通常是用来设置或更新文件的访问,更改,和修改时间的属性。

xargs命令详解

xargs 命令也是管道命令中的一员。xargs命令的功能简单来说就是参数代换

管道前面的命令的输出作为后面命令的标准输入。既然是标准输入,所以这里就有一个要求是后面的命令可以在标准输入中读取数据。这个条件还是比较苛刻的,在linux中并不是所有的命令都可以在标准输入设备中读取数据的,能读取的命令数量不多,除了在前面介绍的 cut、grep、wc等命令之外,xargs也是一个可以在标准输入中读取数据的命令。xargs 在标准输入中读取出数据,然后将这些数据作为那些不能从标准输入中读取数据的命令的输入。所以xargs命令,说白了,就是用来传递数据的。
下面我们举个简单的例子来看一下 xargs 命令的作用

[root@xx ~]# echo /home/ydxxcj | ls
anaconda-ks.cfg file1 file2 file3 new OracleLinux-R7-U9-Server-x86_64-dvd.iso

上面这个例子是想 用 ls 显示 php 目录下的内容,但是很遗憾,ls不是管道命令,不能从标准输入设备上读取数据,所以它不会显示 /home/ydxxcj目录下的内容。因为我们当前是在/root目录下面,所以说,上面的命令会显示 root目录下的内容。
但是,如果我们使用 xargs 命令来做一个数据传递,那将会是另一种结果了

[root@xx ~]# echo /home/ydxxcj | xargs ls
fi\e
[root@xx ~]#

xargs 后面的默认命令是echo 。
大多数的时候,xargs命令都是和管道一起使用的,不过,它也是可以单独使用的。
输入 xargs 按下回车以后,终端就开始等待用户的输入,并且将用户的输入作为标准输入。我们可以输入任意的内容,然后按下 ctrl+d 结束输入。这是echo命令就会把我们输入的内容显示出来。

-d 参数与分隔符

默认情况下,xargs是使用空格作为分隔符将标准输入设备中的数据进行分割,并生成一个个命令的参数,例如

[root@xx ydxxcj]# echo d1 d2 d3 | xargs mkdir
[root@xx ydxxcj]# ll
总用量 0
drwxr-xr-x 2 root root 6 10月 27 20:28 d1
drwxr-xr-x 2 root root 6 10月 27 20:28 d2
drwxr-xr-x 2 root root 6 10月 27 20:28 d3
-rw-rw-r-- 1 ydxxcj ydxxcj 0 10月 27 19:11 fi\e
[root@xx ydxxcj]#

如果可以自定义分隔符,如下面使用冒号作为分隔符

 

$ echo "dir1:dir2:dir3" | xargs -d ":" mkdir

-0 与find命令

由于xargs默认将空格作为分隔符,所以不太适合处理文件名,因为文件名可能包含空格。
find命令有一个特别的参数 -print0,指定输出的文件列表以null分隔。然后,xargs命令的-0参数表示用null当作分隔符。

$ find /path -type f -print0 | xargs -0 rm

上面命令删除/path路径下的所有文件。由于分隔符是null,所以处理包含空格的文件名,也不会报错。

还有一个原因,使得xargs特别适合find命令。有些命令(比如rm)一旦参数过多会报"参数列表过长"的错误,从而而无法执行,改用xargs就没有这个问题,因为它可以对每个参数执行一次命令。

$ find . -name "*.txt" | xargs grep "abc"

上面命令找出所有 TXT 文件以后,对每个文件搜索一次是否包含字符串abc。

  xargs结合find使用 用rm 删除太多的文件时候,可能得到一个错误信息:/bin/rm Argument list too long. 

    用xargs去避免这个问题: 

1
find . -type f -name "*.log" -print0 | xargs -0 rm -f xargs

jps: -0将作为定界符。 

    统计一个源代码目录中所有php文件的行数: 

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

     查找所有的jpg 文件,并且压缩它们: 

1
find . -type f -name "*.jpg" -print | xargs tar -czvf images.tar.gz

实验-locate
updatedb
locate passwd

实验-find
find / -name passwd
find / -user qin
find /etc -size
find /etc/ -size +1M
find /etc/ -size -1M
find /dev -type c -and -name tty*
find /dev -type c -not -name tty*

rm -rf /tmp/*
find /etc/ -size +1M -exec ls -lh {} \;
find /etc/ -size +1M -exec cp -rf {} /tmp \;
ll /tmp

实验-文件操作指令
cat > test << EOF
1
11
213
123
23
21
3
123
123
123213
123213
123213
123213
123213
123213
EOF

cat /etc/passwd | wc -l
cat /etc/passwd | sort -n -t : -k 3
uniq -c file1 | sort -n
df -Th | grep sda1 | tr -s " " | cut -d" " -f 6

实验-tar
tar czvf `date +%F`.log.tar.gz /var/log/
tar xzvf 2016-03-09.log.tar.gz -C /tmp/