使用xargs在带有参数的多个输入列表上运行bash脚本

时间:2019-02-20 17:44:55

标签: bash xargs

我试图在多个文件列表上运行脚本,同时还并行传递参数。我有file_list1.dat,file_list2.dat,file_list3.dat。我想运行接受3个参数的script.sh:arg1、arg2、arg3。

对于一次跑步,我会这样做:

sh script.sh file_list1.dat $arg1 $arg2 $arg3

我想对所有文件列表并行运行此命令。

我的尝试

Ncores=4
ls file_list*.dat | xargs -P "$Ncores" -n 1 [sh script.sh [$arg1 $arg2 $arg3]]

这将导致错误:-P选项的数字无效。我认为此命令的顺序是错误的。

我的第二次尝试:

echo $arg1 $arg2 $arg3 | xargs ls file_list*.dat | xargs -P "$Ncores" -n 1 sh script.sh

但这会导致错误:xargs:ls:被信号13终止

关于使用xargs将参数传递到bash脚本的正确语法是什么的任何想法?

1 个答案:

答案 0 :(得分:0)

我不确定我确切地了解您想要做什么。是否可以并行执行这些命令?

sh script.sh $arg1 $arg2 $arg3 file_list1.dat
sh script.sh $arg1 $arg2 $arg3 file_list2.dat
sh script.sh $arg1 $arg2 $arg3 file_list3.dat
...etc

如果是的话,这应该可以工作:

Ncores=4
printf '%s\0' file_list*.dat | xargs -0 -P "$Ncores" -n 1 sh script.sh "$arg1" "$arg2" "$arg3"

您的版本中的两个主要问题是您将“ Ncores”作为文字字符串传递(而不是使用$Ncores来获取变量的值),并且您在[ ]命令和参数(与外壳语法无关)。我还在所有变量引用周围添加了双引号(通常是一种很好的做法),并使用printf '%s\0'(和xargs -0)代替了ls

为什么我使用printf而不是ls?因为lsprintfecho上没有做任何有用的事情,或者在其他方面做不到的事情。您可能认为ls是获取文件名列表的工具,但是在这种情况下,通行符file_list*.dat会在命令运行之前扩展为 文件列表; ls所要做的就是看每个,对自己说“是的,那是一个文件”,然后打印出来。 echo可以以更少的开销执行相同的操作。但是使用lsecho时,如果任何文件名包含空格,引号或其他有趣的字符,则输出可能是不明确的。某些版本的ls试图通过添加引号或带有有趣字符的文件名 来“解决”此问题,但这可能与xargs解析其输入的方式不匹配(如果它完全发生了。)

但是printf '%s\0'明确且可预测-它打印每个字符串(在这种情况下为文件名),后跟一个NULL字符,而这正是xargs -0的输入内容,因此没有混淆的机会或误判。

好吧,有一个极端的情况:如果没有任何匹配的文件,通配符模式将按字面意义通过,并且最终将尝试使用未扩展的字符串“ file_list *”运行脚本.dat”作为参数。如果要避免这种情况,请在此命令前使用shopt -s nullglob(然后在shopt -u nullglob之前返回正常模式)。

哦,还有一件事:sh script.sh不是运行脚本的最佳方法。在脚本开头添加适当的shebang行(如果仅使用基本shell功能,则使用#!/bin/sh,如果使用任何bashisms,则使用#!/bin/bash#!/usr/bin/env bash),并使用./script.sh

相关问题