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

问题描述 投票:0回答:1

我试图在多个文件列表上运行脚本,同时也并行传递参数。我有file_list1.dat,file_list2.dat,file_list3.dat。我想运行script.sh,它接受3个参数: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脚本的正确语法的任何想法?

bash xargs
1个回答
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来获取变量的值),并且您在命令和参数周围有[ ](这不是任何相关的shell语法)。我还在所有变量引用周围添加了双引号(通常是一种很好的做法),并使用printf '%s\0'(和xargs -0)代替ls

为什么我使用printf而不是ls?因为ls在这里没有做任何有用的事情,printfecho或其他什么都不能做。您可以将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线(#!/bin/sh,如果它只使用基本的shell特征,#!/bin/bash#!/usr/bin/env bash,如果它使用任何bashisms),并用./script.sh运行它。

© www.soinside.com 2019 - 2024. All rights reserved.