当前位置: 首页 > ds >正文

管道符_+xargs拓展参数传递操作,以及find指令

一个简单的例子:

我想删除tex2,但是保留tex1以及其他文件(更一般的,我想删除某种pattern模式下某个子集文件,但是保留其他在该匹配模式下的文件

ls -lh | grep -v tex1 | rm tex

但是真实删除的却是所有的tex*文件,我本意是想删除tex2的,所以是为什么呢 ?

道理很简单:

管道符 | 的作用是将前一个命令的输出传递给后一个命令的标准输入。然而,rm tex* 并不会读取标准输入,而是直接根据当前目录下的文件匹配模式 tex* 删除文件。

说白了就是rm正常实现下是无法接受上一个命令的标准输出的,也就是rm不会读取标准输入。

因此,rm tex* 忽略了 grep 的输出,直接删除了所有以 tex 开头的文件。

事实上,大多数命令都不接受标准输入作为参数,只能直接在命令行输入参数,这导致无法用管道命令传递参数。

正确的实现方法如下:

1,使用 xargs

也就是拓展管道命令符的参数传递command,能够捕获一个命令的输出,然后传递给另外一个命令,正好弥补了一些命令无法单纯使用管道符传递参数的缺点;

编辑

命令格式:

command1 | xargs -para command2# 注意xargs是放在前面1个命令的后面,然后xargs有自己的参数(para等),再紧跟着自己的命令,
# 即用于沟通前面1个command1,以及后面1个command2

一些参数:
编辑

编辑

举例如下:

使用vim定义一个测试文件,内有多行文本数据:

如果只是单纯输出的话,cat或者more都只能多行输出

编辑

如果使用xargs传递参数的话,相当于和xargs的默认命令echo联用,可以整个单行输出;

即xargs 默认的命令是 echo,这意味着通过管道传递给 xargs 的输入将会包含换行和空白,不过通过 xargs 的处理,换行和空白将被空格取代。

说白了就是将前面的标准输出都当作是参数过滤过来了,然后将所有的参数都echo出来。

多行输入单行输出:

编辑

可以看到,本质上和echo联用的命令是一致的,但是单纯使用echo的话不行。

我们可以查看一下这个文件的一些转义字符之类的特殊字符的分布:
参考我的博客:如何查看某个文件中的特殊符号-CSDN博客

编辑

我们可以调整一下一次传递的参数个数,实际上就是一次打印echo出来的标准输出,

编辑

-n 选项多行输出:比如说每行传递3个参数,也就是每一行只打印其中的3个标准输出的内容

编辑

-d 选项可以自定义一个定界符:

比如说以字符"X"分割,本质上和awk -F,或者cut -f中的某些特殊分隔符操作类似;

编辑

结合 -n 选项使用:

编辑

使用xargs过滤所有的参数,以X字符为分隔符,然后每行打印2个参数;

xargs一个比较特殊或者说常用的用法:

  • xargs -I {}:-I 选项指定一个替换字符串 {},xargs 会将输入的每一行替换为 {},然后将其传递给后面的命令。

可以理解里面是有一个for循环,xargs 的行为类似于一个隐式的 for 循环,它会逐个处理输入的参数,并将它们传递给指定的命令。虽然 xargs 并不是真正的循环语句,但它的功能与 for 循环非常相似,尤其是在处理多个输入项时。

基本原理

  • xargs 从标准输入(stdin)读取数据。
  • -I {} 指定一个占位符(通常是 {}),xargs 会将输入的每一行替换为这个占位符。
  • 替换后的结果会被传递给后续的命令。

xargs -I 指定占位符参数

示例1:对文件中的每一行执行命令

假设有一个文件 names.txt,内容如下:

Alice
Bob
Charlie
目标:为每个人创建一个目录

使用 xargs -I {} 可以实现:

cat names.txt | xargs -I {} mkdir {}
  • cat names.txt:将文件内容输出到标准输出。
  • xargs -I {}:指定占位符为 {}
  • mkdir {}xargs 会将每一行替换为 {},然后执行 mkdir 命令。

执行结果:

  • 创建了三个目录:AliceBobCharlie

不一定指定占位符为{},也可以是x

示例2:对文件中的每一行执行多个参数的命令

假设有一个文件 commands.txt,内容如下:

echo Hello
echo World
echo Linux
目标:执行文件中的每条命令

使用 xargs -I {} 可以实现:

cat commands.txt | xargs -I {} sh -c {}
  • cat commands.txt:将文件内容输出到标准输出。
  • xargs -I {}:指定占位符为 {}
  • sh -c {}xargs 会将每一行替换为 {},然后通过 sh -c 执行命令。

执行结果:

Hello
World
Linux

示例3:处理文件列表

假设有一个文件 files.txt,内容如下:

file1.txt
file2.txt
file3.txt
目标:将每个文件的内容追加到一个新的文件 combined.txt

使用 xargs -I {} 可以实现:

cat files.txt | xargs -I {} cat {} >> combined.txt
  • cat files.txt:将文件内容输出到标准输出。
  • xargs -I {}:指定占位符为 {}
  • cat {} >> combined.txtxargs 会将每一行替换为 {},然后执行 cat 命令,将文件内容追加到 combined.txt

执行结果:

  • combined.txt 包含了 file1.txtfile2.txtfile3.txt 的所有内容。

示例4:批量处理图片文件

假设当前目录下有多个图片文件:

image1.jpg
image2.jpg
image3.jpg
目标:将所有图片文件复制到 /data/images 目录下

使用 xargs -I {} 可以实现:

ls *.jpg | xargs -I {} cp {} /data/images
  • ls *.jpg:列出当前目录下所有 .jpg 文件。
  • xargs -I {}:指定占位符为 {}
  • cp {} /data/imagesxargs 会将每个文件名替换为 {},然后执行 cp 命令,将文件复制到 /data/images

执行结果:

  • /data/images 目录下包含了 image1.jpgimage2.jpgimage3.jpg

示例5:批量重命名文件

假设当前目录下有多个文件:

file1.txt
file2.txt
file3.txt
目标:将所有文件重命名为 new_file1.txtnew_file2.txtnew_file3.txt

使用 xargs -I {} 可以实现:

ls *.txt | xargs -I {} mv {} new_{}
  • ls *.txt:列出当前目录下所有 .txt 文件。
  • xargs -I {}:指定占位符为 {}
  • mv {} new_{}xargs 会将每个文件名替换为 {},然后执行 mv 命令,将文件重命名为 new_file1.txt 等。

执行结果:

  • 文件被重命名为 new_file1.txtnew_file2.txtnew_file3.txt

总结

xargs -I {} 是一个非常灵活的工具,可以将输入的每一行数据替换为占位符 {},并将其传递给后续的命令。

现在回到我们的问题,比如说我新建了4个text文件,然后我只想保留text1,但是其余的text*文件我都想要删除(比如说这里text+text2-4都想删除,或者指定2-4删除),或者更复杂一点的命令:

ls -lh | grep -v tex1 | awk '{print $NF}' 

$NF:表示当前行的最后一个字段(NF 是 awk 中的内置变量,表示字段数)

因为ls -lh实际上print在屏幕上的输出也可以看作是一个标准输出(一个文本文件),所以文件名实际上是可以使用awk获取的,直接打印最后一列,$NF(number of filed,也就是列数);

比如说:

ls -lh | grep -v text1 | ls -lh text*  | awk '{print $NF}'

ls -lh | grep -v text1 | ls -lh text*  | awk '{print $NF}' | xargs -I {} rm {}

当然也可以

ls -lh | grep -v tex1 | awk '{print $NF}' | xargs rm

xargs -I {} 并不局限于只能读取每行标准输出的参数,也不一定每次只能读取一行。它的行为可以根据输入数据的格式以及 xargs 的其他选项进行调整。以下是一些更详细的解释和扩展说明:

xargs 的输入来源

xargs 的输入可以来自多种来源,包括:

  1. 标准输入(stdin):通过管道(|)或重定向(<)传递给 xargs
    • 例如:
cat arg.txt | xargs -I {} echo {}

或者:

xargs -I {} echo {} < arg.txt
  1. 文件内容:直接从文件中读取内容。
    • 使用 -a 选项:
xargs -a arg.txt -I {} echo {}

输入数据的格式

xargs 默认会将输入数据视为由空格、制表符或换行符分隔的多个参数。不过,可以通过以下方式调整输入数据的处理方式:

  1. 按行处理
    • 默认情况下,xargs 会将输入数据按行处理,每行视为一个参数。
    • 如果输入数据是多行的,xargs 会逐行处理。
    • 例如:
cat arg.txt | xargs -I {} echo {}

如果 arg.txt 的内容是:

aaa
bbb
ccc

输出结果为:

aaa
bbb
ccc
  1. 按空格或制表符分隔
    • 如果输入数据是用空格或制表符分隔的,xargs 会将它们视为多个参数。
    • 例如:
echo "aaa bbb ccc" | xargs -I {} echo {}

输出结果为:

aaa bbb ccc
  1. 自定义分隔符
    • 使用 -d 选项可以指定输入数据的分隔符。
    • 例如,如果输入数据用逗号分隔:
echo "aaa,bbb,ccc" | xargs -d, -I {} echo {}

输出结果为:

aaa
bbb
ccc

每次处理的参数数量

xargs 的行为可以通过以下选项进行调整:

  1. -n** 选项**:
    • 指定每次传递给命令的参数数量。
    • 例如:
echo "aaa bbb ccc" | xargs -n 2 -I {} echo {}

输出结果为:

aaa bbb
ccc

这里,-n 2 表示每次传递两个参数给 echo 命令。

  1. -I** 选项**:
    • 指定一个替换字符串 {}xargs 会将输入的每个项目替换为 {},并传递给命令。
    • 如果不使用 -nxargs 默认会将每个输入项目单独传递给命令。
    • 例如:
echo "aaa bbb ccc" | xargs -I {} echo {}

输出结果为:

aaa
bbb
ccc
  1. -0** 选项**:
    • 如果输入数据是以 null(\0)字符分隔的,可以使用 -0 选项。
    • 这在处理包含空格、换行符等特殊字符的文件名时非常有用。
    • 例如:
find . -type f -print0 | xargs -0 -I {} echo {}

这里,find 命令的 -print0 选项会以 null 字符分隔文件名,xargs -0 会正确处理这些文件名。

总结

  • xargs -I {} 不仅可以处理每行输入,还可以根据输入数据的格式和 xargs 的其他选项进行灵活调整。
  • 通过 -n 可以控制每次传递的参数数量,通过 -d 可以指定分隔符,通过 -0 可以处理以 null 分隔的输入。
  • xargs 是一个功能强大的工具,可以根据具体需求灵活使用。

参考:Linux xargs 命令 | 菜鸟教程

2,使用find命令:

除了使用xargs,还可以使用find命令,

参考:https://www.runoob.com/linux/linux-comm-find.html

find参数传递的命令格式也很简单,就是

-exec  执行动作的命令 {}  \

其中{}也是一个占位符,指代前面的文件;

比如说:

find . -name "tex*" ! -name "tex1" -exec rm {} \;

具体实施就是:

我只想保留te1,其余的te*都删除

这里其实涉及到find命令的组合命令了,也就是条件组合表达形式:

其中逻辑运算符中and是默认的,所以一般命令看起来是连写的:

比如说:

find . -name "te*" -and -size 0  -exec echo "deleting:" {} \; -exec rm {} \;

在当前目录下寻找文件名匹配/通配te*的文件,且文件尺寸为0的文件,在提醒删除的同时,将该文件删除

回归问题:

find . -name "te*" ! -name "te1"  -exec rm {} \;

总之就是:
在当前目录下寻找文件名匹配/通配te*的文件,但是排除te1文件,然后将每一个文件名都传递给{}占位符,然后对这些占位符执行rm删除命令

至于exec,其实是可以同时执行多项组合操作:

find 可以通过多个 -exec 或其他操作选项同时执行多种操作。例如:

示例 1:同时打印文件名和删除文件

find . -name "*.log" -exec echo "Deleting:" {} \; -exec rm {} \;

示例 2:查找并移动文件

find . -name "*.txt" -exec mv {} /path/to/destination/ \;

示例 3:查找并压缩文件

find . -name "*.log" -exec gzip {} \;

xargs可以和find联用:

比如说上面倒数第2个的命令,使用-print其实就是将找到文件路径打印到标准输出(通常是终端),然后再经过xargs过滤参数传递给tar命令

http://www.xdnf.cn/news/4921.html

相关文章:

  • 真相与幻象的博弈:AI“幻觉”的生成密码与治理革命
  • 稀疏数组在组合优化中的典型应用场景
  • 数据透视表控件DHTMLX Pivot v2.1发布,新增HTML 模板、增强样式等多个功能
  • 快速上手知识图谱开源库AmpliGraph教程指南(二)
  • 深入探索 JavaScript 中的模块对象
  • 算法中的数学:约数
  • 【嵌入式开发-xxxxx】
  • 基于51单片机的步进电机控制系统—正/反转、加/减速
  • HarmonyOS-hdc远程网络方式连接设备
  • PVP鼠标推荐(deepseek)
  • leetcode 242. Valid Anagram
  • 技术视界 | 青龙机器人训练地形详解(三):复杂地形精讲之台阶
  • cpp自学 day24(STL初步认识)
  • 73页最佳实践PPT《DeepSeek自学手册-从理论模型训练到实践模型应用》
  • 自研MCU芯片闪存驱动的实现:OpenOCD详细过程记录与操作指南
  • 2.1 点云数据存储格式——引言
  • 正则表达式实用指南:原理、场景、优化与引擎对比
  • 【LangChain基础系列】深入全面掌握文本加载器
  • PH热榜 | 2025-05-08
  • 安防多协议接入/视频汇聚平台EasyCVR助力工地/工程/建筑施工领域搭建视频远程监控系统
  • [git]如何关联本地分支和远程分支
  • 网络安全赛题解析
  • SEMI E40-0200 STANDARD FOR PROCESSING MANAGEMENT(加工管理标准)-(三)完结
  • 用于构建安全AI代理的开源防护系统
  • Java 基础知识点——数组相关
  • 使用Mathematica内置函数绘制Sierpinski地毯
  • rce-labs level 3,4,5
  • 3.2.3 掌握RDD转换算子 - 5. 合并算子 - union()
  • 飞云分仓操盘副图指标操作技术图文分解
  • 平板收银系统、国产系统,鸿蒙系统,小键盘的封装与应用—仙盟创梦IDE