我在hdfs的文件夹中有一堆.gz文件.我想将所有这些.gz文件解压缩到hdfs中的新文件夹.我该怎么办?
我可以想到通过3种不同的方式来实现它.
使用Linux命令行
以下命令对我有用.
hadoop fs -cat /tmp/Links.txt.gz | gzip -d | hadoop fs -put - /tmp/unzipped/Links.txt
我的gzip压缩文件是Links.txt.gz
输出存储的/tmp/unzipped/Links.txt
使用Java程序
在Hadoop The Definitve Guide
书中,有一节介绍Codecs
.在该部分中,有一个程序要使用解压缩输出CompressionCodecFactory
.我正在重新生成该代码:
package com.myorg.hadooptests; import org.apache.hadoop.conf.Configuration; import org.apache.hadoop.fs.FileSystem; import org.apache.hadoop.fs.Path; import org.apache.hadoop.io.IOUtils; import org.apache.hadoop.io.compress.CompressionCodec; import org.apache.hadoop.io.compress.CompressionCodecFactory; import java.io.InputStream; import java.io.OutputStream; import java.net.URI; public class FileDecompressor { public static void main(String[] args) throws Exception { String uri = args[0]; Configuration conf = new Configuration(); FileSystem fs = FileSystem.get(URI.create(uri), conf); Path inputPath = new Path(uri); CompressionCodecFactory factory = new CompressionCodecFactory(conf); CompressionCodec codec = factory.getCodec(inputPath); if (codec == null) { System.err.println("No codec found for " + uri); System.exit(1); } String outputUri = CompressionCodecFactory.removeSuffix(uri, codec.getDefaultExtension()); InputStream in = null; OutputStream out = null; try { in = codec.createInputStream(fs.open(inputPath)); out = fs.create(new Path(outputUri)); IOUtils.copyBytes(in, out, conf); } finally { IOUtils.closeStream(in); IOUtils.closeStream(out); } } }
此代码将gz文件路径作为输入.
您可以执行以下操作:
FileDecompressor
例如,当我执行我的gzip压缩文件时:
FileDecompressor /tmp/Links.txt.gz
我在位置获得了解压缩文件: /tmp/Links.txt
它将解压缩的文件存储在同一文件夹中.因此,您需要修改此代码以获取2个输入参数: and
.
一旦你使这个程序工作,你可以编写一个Shell/Perl/Python脚本来为你拥有的每个输入调用这个程序.
使用Pig脚本
您可以编写一个简单的Pig脚本来实现此目的.
我编写了以下脚本,该脚本有效:
A = LOAD '/tmp/Links.txt.gz' USING PigStorage(); Store A into '/tmp/tmp_unzipped/' USING PigStorage(); mv /tmp/tmp_unzipped/part-m-00000 /tmp/unzipped/Links.txt rm /tmp/tmp_unzipped/
运行此脚本时,解压缩的内容存储在临时文件夹中:/tmp/tmp_unzipped
.此文件夹将包含
/tmp/tmp_unzipped/_SUCCESS /tmp/tmp_unzipped/part-m-00000
在part-m-00000
包含已解压文件.
因此,我们需要使用以下命令显式重命名它,最后删除/tmp/tmp_unzipped
文件夹:
mv /tmp/tmp_unzipped/part-m-00000 /tmp/unzipped/Links.txt rm /tmp/tmp_unzipped/
因此,如果您使用此Pig脚本,则只需要注意参数化文件名(Links.txt.gz和Links.txt).
同样,一旦你使这个脚本工作,你可以编写一个Shell/Perl/Python脚本来为你拥有的每个输入调用这个Pig脚本.
在我的情况下,我不想管道解压缩文件,因为我不确定他们的内容.相反,我想确保将zip文件中的所有文件都提取到HDFS上.
我创建了一个简单的bash脚本.评论应该让你知道发生了什么.下面有一个简短的描述.
#!/bin/bash workdir=/tmp/unziphdfs/ cd $workdir # get all zip files in a folder zips=$(hadoop fs -ls /yourpath/*.zip | awk '{print $8}') for hdfsfile in $zips do echo $hdfsfile # copy to temp folder to unpack hdfs dfs -copyToLocal $hdfsfile $workdir hdfsdir=$(dirname "$hdfsfile") zipname=$(basename "$hdfsfile") # unpack locally and remove unzip $zipname rm -rf $zipname # copy files back to hdfs files=$(ls $workdir) for file in $files; do hdfs dfs -copyFromLocal $file $hdfsdir rm -rf $file done # optionally remove the zip file from hdfs? # hadoop fs -rm -skipTrash $hdfsfile done
获得所有*.zip
在文件hdfs
目录
逐个:复制zip
到临时目录(在文件系统上)
拉开拉链
将所有解压缩的文件复制到zip文件的目录中
清理
我设法让它使用sub-dir结构来处理每个中的许多zip文件/mypath/*/*.zip
.
祝好运 :)