Linux中一个命令不接受管道输入的情况怎么办?

大家好,我叫梁旭。

在使用 Linux 时,您是否遇到过需要将一些命令串在一起,但其中一个不接受管道输入的情况?在这种情况下,我们可以使用 xargs 命令。xargs 可以将一个命令的输出作为参数发送给另一个命令。

在 Linux 中,所有标准应用程序都有三个与之关联的数据流。它们是标准输入流 (stdin)、标准输出流 (stdout) 和标准错误流 (stderr)。这些流在文本上运行,我们使用文本将输入(stdin)发送到命令,响应(stdout)将在终端窗口上显示为文本。错误消息也会在终端窗口 (stderr) 上显示为文本。

Linux 和类 Unix 操作系统的一个重要特性是能够将一个命令的标准输出流传递给另一个命令的标准输入流。第一个命令不关心它的输出是否写入终端窗口,第二个命令不关心它的输入是否来自键盘。

虽然所有 Linux 命令都有三个标准流,但并非所有命令都接受另一个命令的标准输出作为其标准输入流的输入。所以我们不能通过管道输入这些命令。

xargs 是一个使用标准数据流构建执行管道的命令。通过使用 xargs 命令,我们可以使 echo、rm 和 mkdir 等命令接受标准输入作为它们的参数。

xargs 命令

xargs 接受管道输入,也可以接受来自文件的输入。xargs 使用该输入作为我们指定命令的参数。如果我们没有为 xargs 指定特定的命令,则默认使用 echo。xargs 总是产生单行输出,即使输入数据是多行的。

如果我们使用 ls 的 -1(每行列出一个文件)选项,我们会得到一个文件名列表:

$ ls -1 ./*.sh

此命令列出当前目录中的 shell 脚本文件。

如果我们将输出通过管道传输到 xargs 会怎样?

$ ls -1 ./*.sh | xargs

如您所见,输出作为一长串文本写入终端。如您所见,xargs 可以将输出作为参数传递给其他命令。

将 xargs 与 wc 命令一起使用

我们可以使用 xargs 命令轻松地让 wc 命令计算多个文件中的字数、字符数和行数

$ ls *.c | xargs wc

执行结果如下:

运行该命令的结果显示了每个文件的统计信息和总数。

该命令执行以下操作:

使用带有确认消息的 xargs

我们可以使用 -p (交互式)选项让 xargs 提示我们是否要继续进行。

如果我们通过 xargs 将文件名字符串传递给 touch 命令,touch 将创建这些文件。

$ echo 'one two three' | xargs -p touch

终端显示要执行的命令,xargs 等待我们输入 y 或 Y、n 或 N 并回车响应。如果仅按下 Enterlinux命令行界面输错了,则将其视为 n。该命令仅在我们输入 y 或 Y 时执行。

我们按 y 并回车,然后使用 ls 检查文件是否已创建。

$ ls one two three

将 xargs 与多个命令一起使用

我们可以将 xargs 与带有 -I(初始参数)选项的多个命令一起使用。此选项定义替换字符串。无论替换字符串出现在命令行的何处,我们提供给 xargs 的值都会被插入。

有点抽象,我们举例说明。

我们首先使用tree命令查看当前目录下的子目录。-d(目录)选项使树命令忽略文件并且只输出目录。

$ tree -d

现在只有一个子目录 images。

在 directory.txt 文件中,我们有一些我们想要创建的目录的名称。让我们先看看 cat 里面有什么。

$ cat directories.txt

我们将其作为输入数据传递给 xargs 并执行以下命令:

$ cat directories.txt | xargs -I % sh -c 'echo %; mkdir %'

该命令执行以下操作:

命令执行结果:

我们可以用树验证目录是否已创建。

$ tree -d

将文件复制到多个位置

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

首先,将两个目录的名称通过管道传送到 xargs。并且让 xargs 一次只将其中一个参数传递给正在使用的命令。

要调用 cp 两次linux命令行界面输错了,每次使用两个目录之一作为命令行参数,我们可以通过将 xargs 的 -n(最大数量)选项设置为 1 来实现。

-v (verbose verbose) 选项在这里也被用来让 cp 报告它在做什么。

$ echo ~/dir1/ ~/dir2/ | xargs -n 1 cp -v ./*.c

我们将文件复制到两个目录,一次一个。cp 反馈细节,让我们看到发生了什么。

删除嵌套目录中的文件

如果文件名包含空格或其他特殊字符(例如换行符),xargs 将无法正确解释这些文件名。我们可以通过使用 -0(空终止符)选项来解决这个问题。在这种情况下,xargs 将使用空字符作为文件名的最终分隔符。

这里我们以 find 命令为例。find 有自己的选项来处理文件名中的空格和特殊字符,即 -print0(全名,空字符)选项。

$ find . -name "*.png" -type f -print0 | xargs -0 rm -v -rf "{}"

该命令执行以下操作:

该命令执行后,将搜索所有子目录并删除匹配的文件。

删除嵌套目录

假设我们要删除一组嵌套的子目录,首先用树来查看它们。

$ tree -d

$ find . -name "level_one" -type d -print0 | xargs -0 rm -v -rf "{}"

此命令使用 find 在当前目录中递归搜索,定位名为 level_one 的目录,然后通过 xargs 将目录名称传递给 rm。

该命令与前面命令的区别在于,搜索的项目是最顶层目录的名称,-type d 指定要查找的目录,而不是文件。

每个目录的名称在删除时都会打印出来。我们可以再用tree来检查一下效果:

$ tree -d

所有嵌套的子目录已被删除。

删除除一种文件类型以外的所有文件

我们可以使用 find 、 xargs 和 rm 来删除所有类型的文件,只保留我们想要保留的一种类型的文件。这需要提供您要保留的文件类型。

-not 选项告诉 find 返回所有与搜索模式不匹配的文件名。此时我们再次对 xargs 使用 -I(初始参数)选项。这次定义的替换字符串是{}。这与我们之前使用的替换字符串 % 具有相同的效果。

$ find . -type f -not -name "*.sh" -print0 | xargs -0 -I {} rm -v {}

命令执行后,我们用ls确认结果。如您所见,目录中仅保留与 *.sh 匹配的文件。

$ ls -l

使用 Xargs 创建压缩文件

我们可以使用 find 命令搜索文件,并通过 xargs 将文件名传递给 tar 命令以创建压缩文件。

我们将在当前目录中搜索 *.sh 文件。

$ find ./ -name "*.sh" -type f -print0 | xargs -0 tar -cvzf script_files.tar.gz

命令执行的结果将列出所有 .sh 文件并创建一个压缩文件。

> 2020年入选阿里巴巴/腾讯等一线公司面试,简历,进阶,电子书《**良旭Linux**》后台回复《**资讯**》免费获取

####看完都是真爱,请给个大拇指然后离开?你们的“三通”是梁旭继续创作的最大动力!

1.关注**原创**《**良旭Linux**》,第一时间获取最新Linux干货!

2.后台回复【资料】【面试】【简历】,获取入选一线厂商的面试、自我提升、简历等资料。

3. 关注我的博客:[lxlinux.net]()

© 版权声明
THE END
喜欢就支持一下吧
点赞0
分享
评论 抢沙发

请登录后发表评论