我在hdfs的文件夹中有一堆.gz文件.我想将所有这些.gz文件解压缩到hdfs中的新文件夹.我该怎么办?
Man*_*lur 30
我可以想到通过3种不同的方式来实现它.
使用Linux命令行
以下命令对我有用.
hadoop fs -cat /tmp/Links.txt.gz | gzip -d | hadoop fs -put - /tmp/unzipped/Links.txt
Run Code Online (Sandbox Code Playgroud)
我的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);
}
}
}
Run Code Online (Sandbox Code Playgroud)
此代码将gz文件路径作为输入.
您可以执行以下操作:
FileDecompressor <gzipped file name>
Run Code Online (Sandbox Code Playgroud)
例如,当我执行我的gzip压缩文件时:
FileDecompressor /tmp/Links.txt.gz
Run Code Online (Sandbox Code Playgroud)
我在位置获得了解压缩文件: /tmp/Links.txt
它将解压缩的文件存储在同一文件夹中.因此,您需要修改此代码以获取2个输入参数:<input file path> and <output folder>.
一旦你使这个程序工作,你可以编写一个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/
Run Code Online (Sandbox Code Playgroud)
运行此脚本时,解压缩的内容存储在临时文件夹中:/tmp/tmp_unzipped.此文件夹将包含
/tmp/tmp_unzipped/_SUCCESS
/tmp/tmp_unzipped/part-m-00000
Run Code Online (Sandbox Code Playgroud)
在part-m-00000包含已解压文件.
因此,我们需要使用以下命令显式重命名它,最后删除/tmp/tmp_unzipped文件夹:
mv /tmp/tmp_unzipped/part-m-00000 /tmp/unzipped/Links.txt
rm /tmp/tmp_unzipped/
Run Code Online (Sandbox Code Playgroud)
因此,如果您使用此Pig脚本,则只需要注意参数化文件名(Links.txt.gz和Links.txt).
同样,一旦你使这个脚本工作,你可以编写一个Shell/Perl/Python脚本来为你拥有的每个输入调用这个Pig脚本.
如果您有压缩的文本文件,hadoop fs -text 支持 gzip 以及其他常见的压缩格式(snappy、lzo)。
hadoop fs -text /tmp/a.gz | hadoop fs -put - /tmp/uncompressed_a
Run Code Online (Sandbox Code Playgroud)
在我的情况下,我不想管道解压缩文件,因为我不确定他们的内容.相反,我想确保将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
Run Code Online (Sandbox Code Playgroud)
*.zip在文件hdfs目录zip到临时目录(在文件系统上)我设法让它使用sub-dir结构来处理每个中的许多zip文件/mypath/*/*.zip.
祝好运 :)