如何在Linux中使用强大的Xargs命令

时间:2020-03-05 15:30:13  来源:igfitidea点击:

Xargs是Linux中最强大的命令之一。
在本教程中,将介绍如何将标准输入转换为命令的Xarg。

什么是xargs命令?

XARGS命令从标准输入或者从另一个命令的输出读取文本行,并将它们转换为命令并执行它们。

我们通常会发现Xargs命令与Find命令一起使用。
Find命令为我们提供文件名列表,Xargs命令允许我们使用那些文件名,一个逐个文件,就像它被输入到另一个命令一样。

由于Xargs在重定向上工作,我强烈建议在Linux中刷新我们对STDIN,STDOUT和PIPE重定向的知识。

如何使用Xargs命令?

Xargs命令具有以下语法:

xargs [options] [command [initial-arguments]]

但你可能不会像这样使用它。
它的力量在于将一个命令的输出组合给另一个命令。
让我们用一个简单的例子看到它。

在我当前的目录中,我有一些文本文件,flowers.txt有所有这些文件的名称:

Hyman@theitroad:~/tutorial$ls
flowers.txt  lily.txt  one_lotus.txt  rose.txt  three_lotus.txt  two_lotus.txt
Hyman@theitroad:~/tutorial$cat flowers.txt 
lily.txt
one_lotus.txt
rose.txt
three_lotus.txt
two_lotus.txt

现在我的目标是我想看到flowers.txt中提到的所有文件的文件大小。
常识说我可以组合CAT命令来显示所有文件名,然后将其管制到du命令以检查文件大小。

但是如果我直接管道,它不会给出flowers.txt文件中提到的每个文件的大小。

Hyman@theitroad:~/tutorial$du -h
52K	.
Hyman@theitroad:~/tutorial$cat flowers.txt | du -h
52K	.

为什么?
首先,du命令不采用标准输入。
其次,CAT命令的输出不是单独的文件名。
这是一个像新行角色分开的单词。

Xargs命令的魔力是它将采用此功能和文本由空格或者新行分隔,并将其转换为单个输入到下一个命令。

Hyman@theitroad:~/tutorial$cat flowers.txt | xargs du -h
4.0K	lily.txt
4.0K	one_lotus.txt
16K	rose.txt
4.0K	three_lotus.txt
16K	two_lotus.txt

将其视为等同于将这些文件名送到du命令:

Hyman@theitroad:~/tutorial$du -h lily.txt one_lotus.txt rose.txt three_lotus.txt two_lotus.txt 
4.0K	lily.txt
4.0K	one_lotus.txt
16K	rose.txt
4.0K	three_lotus.txt
16K	two_lotus.txt

你现在意识到Xargs命令的力量,不是吗?

Xargs并找到:彼此制作

我们通常会发现它与"查找命令"的组合使用。
find命令搜索文件和目录,它返回其名称。
感谢XARGS,我们可以使用Find命令的结果以获取特定目的,如重命名它们,移动它们,删除它们以及否则。

让我们说,你想获得以.txt结尾的所有文件,并包含红色字。
我们可以在Xargs的帮助下组合"查找和Grep"命令:

Hyman@theitroad:~/tutorial$find . -type f -name "*.txt" | xargs grep -l red
./three_lotus.txt
./two_lotus.txt
./rose.txt

处理带有空格的文件名

如果名称中有空间的文件,则会导致问题。
让我们说我将三个rotus.txt重命名为"三个lotus.txt"。
现在,当它通过XARG进行处理时,它被视为两个单独的文件,为三个和lotus.txt。

Hyman@theitroad:~/tutorial$find . -type f -name "*.txt" | xargs grep -l red
./two_lotus.txt
grep: ./three: No such file or directory
grep: lotus.txt: No such file or directory
./rose.txt

在这种情况下,我们应该使用"查找"命令的-Print0选项。
它将线与ASCII NULL字符分开而不是换行符。
同样,我们还应该使用带有-0的xargs来接受ASCII空。

Hyman@theitroad:~/tutorial$find . -type f -print0 -name "*.txt" | xargs -0 grep -l red
./two_lotus.txt
./three lotus.txt
./rose.txt

查看正在执行的命令

如果要查看在XARG的帮助下正在执行哪个命令,则可以使用-t选项。
它将打印正在执行的实际命令。

Hyman@theitroad:~/tutorial$find . -type f -name "*.txt" | xargs -t touch
touch ./three_lotus.txt ./two_lotus.txt ./lily.txt ./rose.txt

在运行命令之前,强制XARGS提示确认

某些情况需要删除文件时要特别小心。
看到将执行哪些命令并具有拒绝执行的选项将是一个好主意。

我们可以使用-p选项xargs来获取提示。

Hyman@theitroad:~/tutorial$find . -type f -name "*.txt" | xargs -p rm
rm ./three_lotus.txt ./two_lotus.txt ./lily.txt ./rose.txt ?...n

使用占位符与XARGS获得更多控制权

默认情况下,XARGS命令将标准输入添加为命令末尾的参数。
当我们需要在最后一个参数之前使用该问题时,这会产生问题。

例如,如果使用MOVE命令,则首先需要源,然后是目标。

如果要将找到的文件移动到目标目录,则此命令将无法正常工作:

Hyman@theitroad:~/tutorial$find . -type f -name "*.txt" | xargs -p mv new_dir
mv new_dir ./three_lotus.txt ./two_lotus.txt ./lily.txt ./rose.txt ?...y
mv: target './rose.txt' is not a directory

这是我们可以使用xargs中的占位符与选项 - 这是如此:

Hyman@theitroad:~/tutorial$find . -type f -name "*.txt" | xargs -p -I {} mv {} new_dir
mv ./three_lotus.txt new_dir ?...n
mv ./two_lotus.txt new_dir ?...n
mv ./lily.txt new_dir ?...n
mv ./rose.txt new_dir ?...n

想到它,好像xargs从查找命令获取所有文件名并将其保留在{}中。
然后它进入MV命令并提供{}的内容。

这里的主要区别是,它不是将所有文件名放在同一命令中,而是将它们逐个添加。
这就是为什么MV命令已被调用每个参数(如上样示例所示,因为我们可以看到)。

注意:我使用{}作为占位符。
我们可以作为占位符的大多数其他字母或者角色。
{}是安全的,易于理解和区分。

使用xargs运行多个命令

我们可以使用占位符使用Xargs运行多个命令。

Hyman@theitroad:~/tutorial$find . -type f -name "*.txt" | xargs -I {} sh -c 'ls -l {}; du -h {}' 
-rw-rw-r-- 1 igi igi 0 Jan 28 17:02 ./three_lotus.txt
0	./three_lotus.txt
-rw-rw-r-- 1 igi igi 0 Jan 28 17:02 ./two_lotus.txt
0	./two_lotus.txt
-rw-rw-r-- 1 igi igi 0 Jan 28 17:02 ./lily.txt
0	./lily.txt
-rw-rw-r-- 1 igi igi 0 Jan 28 17:02 ./rose.txt
0	./rose.txt

请记住,占位符不会扩展到下一个管道重定向或者其他命令。