5

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

#!/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) 中运行,否则将变得不可行。

4

3 回答 3

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

在文件名中也使用单引号,您必须更加努力地工作。

于 2011-06-13T05:26:30.340 回答
1

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

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

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

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

我希望这有帮助。

于 2011-06-13T04:42:58.500 回答
1

在文件名中也使用单引号,您必须更加努力地工作。

这是一种在文件名(或文件路径)中转义单引号的方法,它将eval在被单引号包围的变量中得到 'ed。

(
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}"
)
于 2011-06-14T14:42:10.820 回答