重定向命令的输出分别在每个文件的xargs下运行

时间:2015-04-15 13:43:10

标签: sqlite csv xargs

我正在尝试使用xargs从cmd行将一堆sqlite表转储为.csv格式,即

find . -name "*.db" -print0 \
  | xargs -0 -I {} sqlite3 -header -csv {} "select * from pulse_data;" > {}.csv

由于某种原因,它依次写入{}.csv而不是每个.db文件。

使用{}表示法多次出现问题?

如果我在没有重定向的情况下运行它,它似乎按预期工作,即

find . -name "*.db" -print0 \
  | xargs -0 -I {} sqlite3 -header -csv {} "select * from pulse_data;"

只需按照预期的.csv格式

将所有.db表打印到stdout

如何让它重定向到适当命名的文件,即<file-name>.db.csv

1 个答案:

答案 0 :(得分:1)

xargs无法启动shell,因此您无法从中执行shell重定向(除非您的命令明确xargs sh -c ...)。在问题中给出的代码中,>{}xargs被启动之前由父shell执行 - 它根本不知道重定向尝试。

由于你没有在这里做任何明显受益于xargs(如并行性)的事情,因此在其下启动shell的成本是不合理的。只需从外壳中读取列表即可。

while IFS= read -r -d '' filename; do
  sqlite3 -header -csv "$filename" "select * from pulse_data;" >"$filename.csv"
done < <(find . -name '*.db' -print0)  # See footnote 1

如果确实出于某种原因想要使用xargs:

find . -name '*.db' -print0 \
  | xargs -0 sh -c '
      for filename; do
        sqlite3 -header -csv "$filename" "select * from pulse_data;" >"$filename.csv"
      done' _ {} +

脚注1:请注意<()是POSIX sh中不存在的功能 - 但ksh,zsh和bash都将拥有它;如果您需要与/bin/sh兼容,则可以从find转换为while循环,但请注意this comes with some caveats