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

redirecting output of command run under xargs separately per-file

我正在尝试使用 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 表打印到标准输出

我怎样才能让它重定向到一个适当命名的文件,即 <file-name>.db.csv

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

由于您在这里没有做任何可以显着受益于 xargs(例如并行性)的事情,因此在其下启动 shells 的成本是不合理的。只需从外部 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.