Linux批量文件操作——基于find-xargs

这篇具有很好参考价值的文章主要介绍了Linux批量文件操作——基于find-xargs。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

前言

在项目初创阶段,经常会遇到各种文件操作,拷贝头文件,库,批量重命名等。文件结构一复杂,这就将是个无聊的工作。

查找文件

find可以在目录结构中搜索文件,这是它在man里面的作用描述。那么怎么搜索呢?有多种方式,按文件时间,大小,按文件名,路径名,按文件类型,权限,按用户。而这些方式又可以通过与或非的逻辑相互组合,完成更苛刻的查找工作,简直是文件查找的福音。
通常介绍一种命令都会以命令形式开始,find的格式如下

find [-H] [-L] [-P] [-D debugopts] [-Olevel] [starting-point...] [expression]

[-H] [-L] [-P] [-D debugopts] [-Olevel]这一些统统不重要,
[-H] [-L] [-P]是针对软连接的,不常用。[-D debugopts]是显示运行期间的额外信息,信息太乱太杂,用处不大。[-Olevel]则是用于优化查找的,默认的已经够用,所以也没必要深究。
find的最大魔法在最后的[expression],下面将以实例的形式讲解这个[expression]到底该怎么玩,原始的文件结构如下

├── alice.h
├── andy
│   ├── jack
│   │   └── mary.h
│   ├── mark.cpp
│   ├── mark.h
│   └── pony.txt
├── andy.c
├── bill.cpp
├── bill.h
├── mark.h
└── mary

现在,我想找到以andy命名的文件,命令该怎么写呢。直觉告诉我们应该是

find andy

但是直觉对吗,我们来看输出

andy
andy/mark.cpp
andy/jack
andy/jack/mary.h
andy/pony.txt
andy/mark.h

它只找到了andy目录,甚至都没找到andy.c,那么看来我们需要一种方式告诉find,我们找的东西是文件,不是目录,这个选项就是-type
-type后面需要紧跟一个参数,常用取值是d代表目录,f代表文件。现在我们需要找到文件,那么就应该加个-type f的选项。但这就够了吗?执行命令会发现报错了,因为后面的andy被认为是路径,而我们要找的是文件名啊。所以,这又需要另一个选项的帮忙,-name-name后面可以跟具体的名字或者正则。结合这两个条件,我们得出了最终的命令

find -type f -name "andy*"

这里有两点值得注意,首先-type-name其实是两个独立选项,可以单独使用,也可以联合使用,当联合使用时,他们之间不使用操作符(-o(Or),-a(AND),-not)连接时,就会把-a单做连接符,也就是所有的条件都满足才回出现在最终的结果中。由此,可以延伸出一种反向的查找方法,

find -type f -not -name "andy*"

这个命令就会查找出所有不以andy开头的文件。

./andy/mark.cpp
./andy/jack/mary.h
./andy/pony.txt
./andy/mark.h
./bill.h
./bill.cpp
./mark.h
./alice.h

另一个值得注意的点是"andy*"加了双引号,因为*是特殊字符,所以需要用双引号转椅一下,假如没有特殊字符是不需要添加双引号的。回到最初的命令,为啥第一条我们想当然的命令竟然没有找到我们期盼的目标呢?因为find是严格匹配的,我们只写了andy,而遗漏了后缀.c,这是最容易发生错误的地方。
其实,到这里,我们已经学习了这个命令的50%,那剩下的有什么内容呢?记得find的主要功能吗,里面提到了个目录结构。对的,find还可以控制查找范围。
新需求来了,怎样找到某个目录下所有的直接子.h文件呢?这里的直接和子合起来的意思是查找范围只能是当前目录,不能查找到当前目录的子目录。在解决这个问题前,我们需要知道一个前置知识——两个目录之间存在两种相互关系,兄弟或者父子。兄弟目录深度相同,父子目录深度相差1。知道了这点,再来看需求——.h文件很简单,使用-name "*.h"就能满足。但是,这样会找到andy目录下的.h文件,所以我们需要一种控制目录查找层级的东西,他们就是-mindepthmaxdepth。这两个参数和前面的不一样,他们属于Global options。什么是Global options呢,就是他们的作用是全局性的,并且它们总是返回true,也就是它们和其他的选项连起来一起查找的时候,只用考虑其他选项的条件。并且,为了凸显它们的全局性,它们在命令书写时,必须写在最前面,否则会触发警告。如下,就是写在了-name "*.h"前面。

find -maxdepth 1 -name "*.h"

这两个参数有点反直觉,可以这样理解——最多查找到哪里,有个最多,就是maxdepth,反过来就是从哪里才开始查找,才就是mindepth

聊完了目录结构,名字这些显眼的部分,文件还有访问(access)创建(create)、修改(modiffy)时间,权限(permission),大小(size)这些没有涉及到,而这些也同样可以作为find的查找条件,在开始之前,有一些小规则可以对这些选项做个快速分组——选项会以属性的英文首字母作为开始,如

  • 时间相关的选项有timemin,分别表示某个事件发生的前n天和n分钟,这里的某个事件可以用访问aaccessc创建(create)、m修改(modiffy)替代,它们组合起来就是一个完整的选项,如mmin n就表示查找修改时间在n分钟以内的文件。
  • 以此类推,i代表大小写敏感,如iname,l代表link文件

当然,这些都可能用得不多,实际使用到再查可能还更方便点,但是有两个很好用的选项不得不讲。
考虑以下情况,某天老本发来一堆用户日志文件,让你给这些用户根据使用频次分级,你该怎么办呢?首先,我们可以把日志文件大小作为依据,根据最大最小划分好区间,如(0-100M),然后用定好的级别(如5级)划分出每级区间(0-20,20-40,...),这样我们多次运行命令,就能得到所有的分级情况了。想法是美好的,但是find提供了这种选项了吗?它提供了-size n。我们来试着查找一下0-20区间的文件

find -size 20M

回车,你会发现结果貌似不完全正确,它可能确实找出了一些满足条件的文件,但是有一些满足的却没有找出,问题出现在哪里呢?原来-size n中的n是严格匹配,就是你输入的是20M,它就只找到恰好是20M的文件,而不是我们期望的20M和20M一下的文件。那么有解决方法吗,当然有,就是数字前面加上+-号,+代表大于等于这个值,-代表小于。所以我们查找20M以下的文件的命令应该是

find -size -20M

解决了符号问题,还有单位问题值得注意,也就是-20M中的M。其实-size的标准形式是-size [+-]n[cwbkMG][+-]n都说过了,后面的则单位。它们是以大小递增顺序排列的,说明如下

  • c:字节
  • w:双字节,也就是word
  • b:512字节构成的块,数字n后面没加单位的话,这个是默认值
  • k:1024个字节,也就是kb
  • M:1024 * 1024个字节,也就是Mb
  • c:1024 * 1024 * 1024个字节,也就是Gb

说完了单位的事,我们接着来出来20——40的分级,直接把20改为40吗?当然不,改为40找到的就是小于等于40M的文件了,所以我们需要一种区间标定法,find没有提供直接的选项支持,但是前面说过,选项是可以组合的,也就是我们可以重复使用-size来标识一个区间。也就是

find -size +20M -size -40M

按照这种方法,多次改变值,就可以完成任务啦。
其实上面的方案还有一点小纰漏,就是没有找出直接没用过的用户,也就是size为0的,那把数字改为0,可以吗?答案是可以,但是假如我们想找的是空目录,而不是空文件呢,-size就不能解决了,因为通常空目录的大小不为0.所以,find又提供了个检测文件是否为空的选项-empty,它不仅可以找到空文件,还可以找到空目录。在我们的实例中,使用 find -size 0找到的结果是

./andy/mark.cpp
./andy/jack/mary.h
./andy/pony.txt
./andy/mark.h
./andy.c
./alice.h

没有找出空目录mary。而使用find -empty查找后,结果是

./mary
./andy/mark.cpp
./andy/jack/mary.h
./andy/pony.txt
./andy/mark.h
./andy.c
./alice.h

不仅找到了mary空目录,其他的空文件也找出来了。
至此,find相关的东西已经了解得差不多了。但是,很多时候仅仅找到并不能完全满足我们的需求,我们可能需要把找到的文件复制到其他地方或者删除之类的,能否把这些操作合起来呢?这就要请我们的xargs登场了。

xargs

xargs只有一个简单的功能,就是从标准输入读入内容,构建并执行命令。怎么理解呢?假设我们在执行find命令,find命令执行肯定是有过程,有逻辑的。按照一定的逻辑和过程,find对文件进行逐一评估,假如满足条件,就输出结果。随着命令的执行,结果可能越来越多。假如我们需要对产生的每个结果都执行一条命令呢,这该怎么办?按照一般的思路,当然是将结果保存起来,然后再写个脚本,读取每一条记录,然后执行相应。但是有了xargs,我们不用这么麻烦了,可以一步到位。我们利用管道符将结果从终端连接到xargs中,xargs接收到一条信息,就会将它作为构建命令的参数,就好像我们手动输入了命令那样,构建完成后还会自动执行。最终的结果就是,没产生一个输出,就会产生一条以这个输出为参数的命令,并且这条命令还自动执行,最终的效果就是实现了一条命令实现了多个功能。

将find和xargs结合起来

现在我们挑战升级了,有个需求,需要提取目录下的所有头文件到另一个目录。这个需求可以分为两部分,一部分是找到头文件,这可以用find命令完成。另一部分是复制找到的头文件,这就需要xargs的参与了。

首先是找到头文件。头文件就是以.h结尾的文件(暂不考虑.hpp),这个后缀是出现在名字里的,所以我们可以使用-name "*。h"选项,同时为了避免某些目录名的干扰,我们把类型也做个限定-type f,只查找文件。这第一步就完成了。
第二布就是复制文件啦。复制文件的标准写法是

cp [OPTION]... SOURCE... DIRECTORY

根据这个命令格式,我们需要确定几个参数,源文件当然就是我们查找到的文件啦,这暂时按下不表。目标文件夹,就是我们拷贝到哪里,我们这里暂时就新建一个test的目录吧,目标文件夹就是test。这就结束了吗,还没有。头文件往往需要和他的父目录组成一个依赖路径,所以我们把所有的头文件直接一股脑都拷贝到test目录下是不可取的,这会打乱头文件的依赖关系,我们还得拷贝和头文件相关的父目录。恰巧的是,cp提供了这样的一个选项-parents——它可以拷贝源文件的完成文件名,也就是包含目录。所以问题的关键就来到了源文件这个参数上了。文章来源地址https://www.toymoban.com/news/detail-487899.html

到了这里,关于Linux批量文件操作——基于find-xargs的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • Linux下查找文件(find、grep命令)

    目录 一、find命令 1.按文件名 2.按文件类型查询 3.按照文件大小查找 4.按照文件日期查找 4.1按照创建日期查找 4.2按照修改日期查找 4.3按照访问日期查找 5.按深度查找 5.1查找起始点以下n层的目录,不超过n层  5.2搜距离起始点n层以下的目录(即最少n层) 6.高级查找 6.1-exec  

    2024年01月16日
    浏览(140)
  • Linux基础笔记10 | 文件查找命令 find 详解

    用来在指定目录下查找文件。任何位于参数之前的字符串都将被视为欲查找的目录名。如果使用该命令时,不设置任何参数,则 find 命令将在当前目录下查找子目录与文件。并且将查找到的子目录和文件全部进行显示 学习参考博文:骏马金龙 (junmajinlong.com) 最基础的打印功能

    2024年02月04日
    浏览(91)
  • Linux命令模糊查询文件或文件夹(包含find命令拓展)

    1、 find 命令 ​path(表示文件或文件夹的绝对路径 ​) -type f (表示查的是文件,-type d 表示查的是文件夹 ​) -name “cron*” (表示查cron开头的所有文件或文件夹) 2、 拓展 :

    2024年02月11日
    浏览(88)
  • Ansible批量操作(上传文件、删除文件&指定文件内容、执行sh文件等)

    官方网站 https://www.ansible.com/ 一、Ansible 简介 1、Ansible是新出现的自动化运维工具,完全基于Python开发,集合了众多运维工具(puppet、chef、func、fabric)的优点,实现了批量系统配置、批量程序部署、批量运行命令等功能。 2、Ansible是基于 paramiko 开发的,并且基于模块化工作,

    2024年04月16日
    浏览(53)
  • mac批量提取文件夹的名称,怎么操作?

        mac批量提取文件夹的名称,怎么操作?很多小伙伴想知道在mac电脑上可以一键快速批量的将大量文件夹的名提取出来,而不是采用一个一个名称提取的方法,这是一个有利于提高工作效率的办法,这一项技能在网上几乎找不到解决办法,不过经过小编的多方打听,还是给

    2024年02月16日
    浏览(51)
  • Linux命令手册-通过文件名查找文件(find、which、locate)(详解)

    目录 一、find命令 1、语法格式 2、选项说明 3、命令示范 二、which命令 1、语法格式 2、命令示范 三、locate命令 1、语法格式 2、命令示范: find命令在Linux中作为文件查找使用频次很高,主要有以下几种方式。 1、语法格式 find [路径] [选项] [操作] 路径:可以指定搜索的文件在

    2024年02月15日
    浏览(49)
  • Linux 搜索文件中find和grep命令的区别

    在使用linux时,经常需要进行文件查找。其中查找的命令主要有find和grep。两个命令是有区的。 (1)find命令是根据文件的属性进行查找,如文件名,文件大小,所有者,所属组,是否为空,访问时间,修改时间等。 (2)grep是根据文件的内容进行查找,会对文件的每一行按照给定

    2024年02月16日
    浏览(81)
  • linux中在指定路径中按照文件名模糊查找文件之find命令

    大家在实际项目中,可能有时候在排查问题中需要查找一些系统文件,然后看下对应文件信息。例如日志文件信息,数据文件信息等,太多不方便查找时,就可以使用该相关命令来查找最合适; 精准搜索 find 指定路径 -name \\\"搜索内容\\\" 模糊搜索 find 指定路径 -name \\\"*模糊搜索内

    2024年02月06日
    浏览(101)
  • Linux[find命令]-根据路径和条件搜索指定文件并删除

    find命令:用于根据给定的路径和条件查找相关文件或目录,参数灵活方便,且支持正则表达式,结合管道符后能够实现更加复杂的功能。 基本语法格式:find pathname -options 搜索内容 [其他选项] pathname:用来指定搜索路径。 options:用来指定搜索内容。 搜索内容:用来指定搜索

    2024年02月05日
    浏览(66)
  • Linux如何使用find命令搜索到自己想要的文件呢?

    文件搜素专栏全部文章 如何使用find命令搜索到自己想要的文件 ack 命令的基本用法详解 ag命令的使用详解 在 Linux 中查找文件名包含某个的文件,可以使用  find  命令来实现。 find  命令可以在指定目录下递归搜索文件,并根据指定的条件进行过滤。 下面是使用  fi

    2024年02月03日
    浏览(70)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包