导航

xargs on linux

发布时间:5 months ago 更新时间:4 months ago
Linux

总结

  1. xargs是一个能将命令的输出转换为另一个命令的参数的工具,它能让一些命令例如:echo,rm,和mkdir等接受标准输入作为参数来执行操作。
  2. xargs可以和wc等命令一起使用,并且能够轻松地去统计多个文件的单词数字符数行数
  3. xargs可用于将文件复制到多个位置删除嵌套目录中的文件,以及使用find命令创建归档文件。

为什么使用xargs命令?

  • xargs命令常用于在标准的数据流结构上建立在一个可执行管道。换句话说,你可以使用xargs命令的输出作为参数发送到另一个命令。
  • 所有标准的Liunx实用程序有三个与之相关联的数据流,它们分别为标准输入流(stdin),标准输出流(stdout)和标准错误流(stderr),通过使用xargs命令我们可以让一些命令,例如echorm,和mkdir作为参数接受标准输入。
  • 这些流在文本中运行,我们使用文本向命令发送输入(stdin),并且响应(stdout)作为文本写入终端窗口中。错误的信息也会以文本的形式(stderr)写入到终端窗口中。
  • Linux和Unix操作系统都有一个重要的特性:能够将一个命令的标准输出(stdout)通过管道符传递给另一个命令的标准输入(stdin)中。第一个命令不用在意它的输出没有发送到终端窗口,第二个命令不必在意它的输入不是来自键盘。
  • 尽管所有的Linux命令有三个标准流,但不是所有的命令都接受另一个命令的标准输出作为其标准输入。这也意味着你不能通过管道符向它们输出。
  • 这就是xargs命令的所用之处,我们介绍了一些可实用的xargs命令例子 - 你可以随意跳过任何一个点。这些例子不一定要建立在彼此的基础上。

xargs 命令

  • xargs命令可以接受管道符输入。它也可以从文件中接受输入。xargs使用这个输入作为我们告诉它如何使用这个命令的参数 。如果我们没有告诉xargs如何使用具体的命令,那么它将会默认去使用echo命令。

  • 我们可以使用xargs如何生产单行输出,甚至从多行输入去演示。

  • 如果我们在ls中使用-l(每行列出一个文件)的选项,我们将得到一列文件名

    ls -l ./*.sh
  • 这将会列出当前目录中的shell脚本文件

  • 我们可以得到一个预期的单列。如果我们通过xargs管道符去传递那我们会得到什么?

    ls -l ./*.sh | xargs
  • 这个输出结果会作为一个长串的文本写入终端窗口

  • 正是这种功能使xargs将参数提供给其它的命令

将xargs与wc一起结合使用

  • 我们可以使用xargs命令去轻松地实现让wc命令统计多个文件中的单词数字符数行数

    ls *.page | xargs wc
  • 具体过程如下:

    • ls命令首先会列出所有.page后缀的文件并传递给xargs
    • xargs将这些文件名传递给wc命令
    • wc会将文件名当作接收到的命令行参数来处理
  • 会显示每个文件的统计信息,并附带一个总计的结果

执行前需要确认的xargs用法

  • 我们可以使用-p(交互式)选项让xargs在执行前请求确认是否继续操作

  • 如果我们通过xrags将文件名列表传递给touch命令,touch会为我们创建这些文件

    echo 'one two three' | xargs -p touch
  • 将要执行的命令显示出来,xargs会等待我们输入'y''Y'(确认执行),或者'n''N'(取消执行),然后按Enter键响应

  • 如果你只按下Enter键,系统会默认视为'n'(取消执行),只有输入'y''Y'时,命令才会被实际执行

  • 我们输入了'y'并按下Enter,此时可以使用ls命令来进行查看,确认文件已经被创建成功

    ls one two three

使用xargs命令执行多命令操作

  • 通过使用-l(初始化参数)这个选项,我们可以对xargs使用多个命令

  • 该选项用于定义一个"替换字符串",当命令行中出现该代替字符串时,xargs就会将接受到的参数值插入到相应的位置

  • 让我们使用tree命令去查看当前目录下的子目录结构,通过-d(目录)选项,tree将忽略文件而仅显示目录的信息

    tree -d

image-20250403212228230

  • 在这个当前目录下存在一个名为"images"的子目录

  • 在一个名为"directories.txt"的文件中,存放着我们希望创建的目录名称列表。我们可以使用cat命令去查看其中的内容

    cat directories.txt
  • 我们将把这个文件作为xargs命令的输入数据,具体执行的命令如下:

    cat directories.txt | xargs -I % sh -c 'echo %; mkdir %'
  • 该命令的执行流程解析如下:

    1. cat directories.txt |:将 *directories.txt* 文件的内容**(所有待创建的目录名称)通过管道符**输送给xargs
    2. xargs -I %:定义"%"作为一个替换标记符,后续命令中出现的%都会被实际参数替换
    3. sh -c:这会启动一个新的子shell环境,-c 参数表示从命令行读取要执行的指令
    4. echo %; mkdir %’:这会将执行两个命令,echo % 先打印当前正在处理的目录名,mkdir % 随后创建对应的目录,所有%符号都会被xargs逐行替换为输入的目录名
  • 系统会逐个列出并处理目录项

    image-20250403213539237

  • 我们可以再次使用tree命令来验证目录是否已经被成功创建

    tree -d

将文件复制到多个位置

  • 我们可以使用xargs通过单个命令将文件复制到多个位置

  • 我们将通过管道符把两个目录名作为输入参数传递给xargs,并且我们可以通过参数设置告诉xargs每次只能传递其中的一个参数给目标命令

  • 在本次例子中,操作命令为cp。所以当实际执行时,xargs会分别调用两次cp命令,并且每次只能传递一个命令行参数。实现该功能在于xargs-n(最大参数)选项,此处我们将其设置为1

  • 我们也为cp命令添加了-v(verbose)选项,使其实时显示每个文件的操作详情

    echo ~/Backups/ ~/Documents/page-files/ | xargs -n 1 cp -v ./*.page
  • 文件会被逐个复制到两个目录中,cp命令会显示出每个文件的复制操作过程,让我们可以清晰地看到操作执行的过程

删除嵌套目录中的文件

  • 如果文件名中有空格或者特殊字符(如换行符)xargs命令可能将无法被正确解析。我们可以使用-0(空终止符)选项来解决此问题,这个选项会告诉xargs命令使用空字符作为文件名的终止分隔符

  • 我们将在这个示列中使用find命令。find自带专门处理文件名中有空格和特殊字符的选项。即-print0(full name, null character)选项

    find . -name "*.png" -type f -print0 | xargs -0 rm -v -rf "{}"
  • 具体分解如下:

    1. find . -name "*.png"find命令将会从当前目录"."中进行搜索,查找所有名称和"*.png"相匹配的文件,并且文件的类型为(-type f)普通文件
    2. -print0:输出的文件名将以空字符(null)作为终止符,并且确保能够正确的去处理含有空格和特殊字符的情况
    3. xargs -0xargs同样会将文件名视为以空字符*(null*)结尾,所以含有空格和特殊字符的文件名不会引发任何解析问题
    4. rm -v -rf "{}"rm命令将会以详细模式显示操作过程(-v),以递归的方式进行查照片嵌套子目录中的内容(-r),并且将会在不经确认的情况下直接删除文件(-f),而其中的"{}"会被每个具体的文件所替代
  • 所有的子目录都会被系统递归搜索,并且删除符合匹配模式的文件

删除嵌套目录

  • 比如我们想要删除一组嵌套的子目录,可以使用tree命令俩查看其目录结构

    tree -d

    image-20250404000613839

    find . -name "level_one" -type d printo | xargs -o rm -v -rf "{}"
  • 这个命令将会使用find命令在当前目录进行递归搜索名为"leve_one"的目录,并且将搜索的结果通过xargs传递给rm命令进行删除

  • 这个命令与前一个命令的关键区别在于:搜索条件是顶层目录名,并且-type d参数告诉find命令只查找目录,而不是文件

image-20250404001554742

  • 在删除每个目录时其名称都会被打印出来,我们可以使用tree命令进行检验:

    tree -d

    image-20250404003421862

  • 所有的嵌套子目录都会被删除

删除其余所有文件,除了要保留的指定文件

  • 我们可以通过组合使用findxargsrm命令实现我们想要保留的特定类型文件并且删除其余所有文件的操作。虽然逻辑看起来很矛盾,但实际需要指定的时我们自己希望所保留的文件类型,而不是要删除的类型

  • -not选项告诉find指令返回不符合搜索模式的文件名。当我们再次使用xargs命令的-l(initial arguments)选项,此次定义的替换字符串被我们定义为"{}",它的功能与之前使用的"%"符号完全一致

    find . -type f -not - name "*.sh" -print0 | xargs -0 -I {} rm -v {}
  • 我们可以通过ls命令进行检验,此时目录中仅剩和"*.sh"相匹配的文件

    ls -l

    image-20250404005536704

使用xargs创建归档(打包)文件

  • 我们可以使用find命令进行查找文件,然后再借助xargs命令将结果传递给tar命令来创建归档文件。

  • 我们将在当前目录下进行搜索,使用"*.page"作为匹配模式,我们会在此目录下查找所有包含.page后缀的文件

    find ./ - name "*.page" -type f -print0 | xargs -0 -tar -cvzf page_files.tar.gz
  • 文件会被按照我们的预期被列出,同时归档文件也会被创建完成image-20250404010715872

数据中转器

  • 一些时候,当你需要将多个命令组合使用时,往往需要借助一个中间工具搭建一个桥梁。xargs命令在能输出数据的命令不支持直接接收管道符输入的命令之间架起了一座桥梁
  • xargsfind命令都包含大量的功能选项,你可以积极地去查阅它们的功能手册以获得完整的使用说明

image-20250404011915186