将已排序的文件与fifos组合在一起

时间:2011-06-13 04:31:13

标签: performance bash fifo

我在目录中有一些已排序的gzip文件。如何将其中一些组合成另一个已排序的gzip文件?现在我正在使用显式的fifos。有没有办法在没有bash的情况下做到这一点?我是一个bash noob,所以请原谅我缺乏风格。

#!/bin/bash
# Invocation ./merge [files ... ]
# Turns an arbitrary set of sorted, gzipped files into a single sorted, gzipped file,
# printed to stdout. Redirect this script's output!
for f in $@
do
    mkfifo $f.raw
    gzcat $f > $f.raw &
    # sort -C $f.raw
done
sort -mu *.raw | gzip -c # prints to stdout.
rm -f *.raw

我希望将其转换为类似......

sort -mu <(gzcat $1) <(gzcat $2) <(gzcat $3) ... | gzip -9c # prints to stdout.

......但不知道怎么做。我是否需要将参数构建为字符串?这有什么神奇的捷径吗?也许map gzcat $@

注意:每个文件都超过10GB(解压缩100GB)。我有一个2TB驱动器,所以这不是一个真正的问题。此外,该程序必须在O(n)中运行,否则变得不可行。

3 个答案:

答案 0 :(得分:3)

您可以将eval和'进程替换'与Bash结合使用。假设基本文件名不包含空格(假设您使用$@而不是"$@"可能就是这种情况),那么就像:

cmd="sort -mu"
for file in "$@"
do cmd="$cmd <(gzip -cd $file)"
done
eval $cmd | gzip -c9 > outputfile.gz

您也可以在最后一行使用bash -c "$cmd"代替eval $cmd。如果文件名中有空格,则必须更加努力。如果名称不包含单引号,则此方法有效:

cmd="sort -mu"
for file in "$@"
do cmd="$cmd <(gzip -cd '$file')"
done
eval $cmd | gzip -c9 > outputfile.gz

在文件名中也使用单引号,你必须更加努力。

答案 1 :(得分:1)

对我来说,你的问题有点不清楚,但如果我理解你的需要,试试这个:

gunzip -c file1 file2 .... | sort | gzip -9 > mergedFile.gz

如果你想在1 dir中执行某种类型的所有文件,那么你可以使用file*.type作为gunzip的输入列表,否则,根据我的例子,你需要明确列出每个文件。

-c选项表示'发送输出到stdout',这是管道读取的,发送到sort,它将输出发送到stdout,管道和gzip,用它来发送stdout被重定向到最终文件。 -9是最高的压缩,它为您提供最小的文件(对于gzip),但需要更长的时间。您可以在-1和-9之间给出一个明确的数字来调整压缩大小/时间以根据需要压缩权衡。

我希望这会有所帮助。

答案 2 :(得分:1)

  

在文件名中也使用单引号,你必须更加努力。

这是一种在单个引号包围的变量中获取eval的文件名(或文件路径)中的单引号的方法。

(
esc="'\''"
file="/Applications/iWork '09/Pages.app"
file="${file//\'/${esc}}"
#echo "'${file}'"; ls -bdl "'${file}'"
evalstr="echo '${file}'; ls -bdl '${file}'"
#set -xv
eval "${evalstr}"
)