从xargs传递命令行参数

时间:2014-06-10 16:48:41

标签: bash shell sed command-line-arguments xargs

我有一个执行以下操作的shell脚本:

INPUT_DIR是一个包含zip文件的目录。 zip文件看起来像lograw1.zip,lograw2.zip等。

我有一个名为prog.py的程序,它使用选项-i将输入作为zip文件输出并输出tsv文件。与每个zip文件对应的tsv文件具有不同的名称。

即,lograw1.zip给出了logproces1.tsv

的输出

我有一个带有for for循环的shell脚本,它运行正常。

for f in $INPUT_DIR/*.zip
  do
    filename=$(basename $f .zip)
    tsvfilename="$(basename "${f/raw/processed}" .zip).tsv"
    python /work/prog.py -i $f  $OUTPUT_DIR/$tsvfilename
  done

我想在bash脚本中使用xargs来读取拉链并提交给我的prog进行类似的文件重命名。如何使用xargs作为命令之间的参数发送? 提前谢谢。

1 个答案:

答案 0 :(得分:4)

xargs的工作方式是从标准输入中获取文件名列表,并运行一个命令,其中包含从标准输入中检索的所有文件。如果标准输入的长度将溢出命令行缓冲区,xargs将分割列表。

让我们做一些简单的事情:

ls | xargs /bin/echo

假设您的目录如下所示:

  • FOO
  • barfoo
  • foobar的
  • BARBAR
  • foofoo

ls命令将输出:

foo bar barfoo foobar barbar foofoo

这将传递给/bin/echo,并执行以下操作:

/bin/echo foo bar barfoo foobar barbar foofoo

现在,假设您的输入缓冲区只有12个字符长,将所有这些文件传递给/bin/echo将超出输入缓冲区。 xargs将确保它不会将超过10个字符的数据传递给/bin/echo命令,并将一遍又一遍地重新执行/bin/echo命令直到所有文件传递给它:

/bin/echo foo bar
/bin/echo barfoo foobar
/bin/echo barber foofoo

您可以将-s10参数传递给xargs,以限制xargs将占用的字符数,从而对此进行测试。您还可以尝试-t,它将完全回显xargs正在执行的内容。


本教程的原因是要了解为了使xargs能够正常工作,shell脚本的每个命令都必须能够使用多个文件,而实际情况并非如此。 /work/prog.py看起来一次只需要一个文件,basename命令也是如此。

您必须修改脚本才能利用xargs才能使其正常运行。可能通过使用for循环来处理这个问题。

考虑将find与您的shell脚本一起使用,它可以做您想做的事情:

find . -name "*.zip" -exec script.sh {} \;

xargs存在问题(默认情况下它不会处理带有时髦字符的文件名),并且有一个问题是它是否更快。毕竟:

rm *

仍然必须一次删除传递给它的文件,就像这个小脚本一样:

for file in *
do
    rm $file
done

在旧的Unix时代,开始一个新进程需要花费很多开销,所以如果你可以运行一次命令而不是多次运行,它可以节省你的时间。我不知道现在是否值得这么麻烦。