我试图在多个文件列表上运行脚本,同时还并行传递参数。我有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脚本的正确语法是什么的任何想法?
答案 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
?因为ls
在printf
或echo
上没有做任何有用的事情,或者在其他方面做不到的事情。您可能认为ls
是获取文件名列表的工具,但是在这种情况下,通行符file_list*.dat
会在命令运行之前扩展为 文件列表; ls
所要做的就是看每个,对自己说“是的,那是一个文件”,然后打印出来。 echo
可以以更少的开销执行相同的操作。但是使用ls
或echo
时,如果任何文件名包含空格,引号或其他有趣的字符,则输出可能是不明确的。某些版本的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
。