xargs:如何控制和使用命令行参数

时间:2020-01-09 10:42:09  来源:igfitidea点击:

我试图通过shell管道使用xargs命令,但无法理解如何控制和使用命令行参数。
例如,如何找出位于100多个子目录中的所有* .c文件,并将它们移至另一个目录~/old.src。
如何将命令行参数与xargs结合使用以实现相同的目的?

xargs命令旨在构造参数列表并调用其他实用程序。

xargs从标准输入或者管道中读取由空格或者换行符分隔的项目,并以任何初始参数执行一次或者多次命令,然后再从标准输入中读取项目。
标准输入上的空白行将被忽略。

xargs更安全易用

可以使用shell的反引号功能实现xargs功能。
但是,它提供了更多选择。
它可以轻松处理文件名中的空格或者特殊字符。
它通常与find,grep和其他命令一起使用。

xargs的例子

例如下面的示例将使用xargs打印1 2 3 4(默认为echo命令)

$ echo 1 2 3 4 | xargs echo

或者

$ echo 1 2 3 4 | xargs

您可以强制xargs在每个命令行中最多使用max-args参数。
例如,以下将在每个命令中使用前两个参数:

$ echo 1 2 3 4 | xargs -n 2

查找当前目录中或者当前目录下的所有.bak文件,并将其删除。

$ find . -name "*.bak" -type f -print | xargs /bin/rm -f

{}作为参数列表标记

{}是默认的参数列表标记。
您需要将{} this与各种命令一起使用,这些命令一次需要两个以上的参数。
例如mv命令需要知道文件名。
以下内容将在当前目录中或者以下找到所有.bak文件,并将它们移至~/.old.files目录:

$ find . -name "*.bak" -print0 | xargs -0 -I {} mv {} ~/old.files

您可以将{}重命名为其他名称。
在下面的示例中,{}重命名为file。
与前面的示例相比,它更具可读性:

$ find . -name "*.bak" -print0 | xargs -0 -I file mv file ~/old.files

其中:

  • `-0'如果有空格或者字符(包括换行符),许多命令将不起作用。此选项照顾空格的文件名。
  • -I用从标准输入中读取的名称替换初始参数中replace-str的出现。同样,未加引号的空格也不会终止输入项目。相反,分隔符是换行符。

用空格和换行符处理文件名

如果有包含换行符或者空格的文件名,则以下内容将无法正常工作(它将找到当前目录中的所有.mp3文件,并使用mplayer播放它们):

$ find . -iname "*.mp3" -print | xargs mplayer

要解决此问题,请使用-0选项:

$ find . -iname "*.mp3" -print0 | xargs -0 -I mp3file mplayer mp3file

要找出位于100个子目录中的所有* .c文件并将其移至另一个目录~/old.src,请使用:

$ find /path/to/dir -iname "*.c" -print0 | xargs -0 -I file mv file ~/old.src

使用xargs避免错误和资源匮乏的问题并找到组合

要将所有媒体文件复制到另一个名为/bakup/iscsi的位置,可以使用cp,如下所示:

$ cp -r -v -p /share/media/mp3/ /backup/iscsi/mp3

但是,如果发生错误(例如,文件数量太大而无法处理cp命令),则cp命令可能会失败。

xargs与find结合可以很好地处理此类操作。

xargs的资源使用效率更高,不会因错误而停止:

$ find /share/media/mp3/ -type f -name "*.mp3" -print0 | xargs -0 -r -I file cp -v -p file --target-directory=/bakup/iscsi/mp3

请注意,以上所有命令均已使用GNU/xargs版本进行了测试。

BSD和UNIX xargs命令可能没有-r之类的选项。
请参考您当地的xargs手册页以获取更多信息:

man xargs