我正在尝试使用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
?
答案 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。