Как распаковать файлы .gz в новый каталог в hadoop?

У меня есть куча файлов .gz в папке в hdf. Я хочу разархивировать все эти .gz файлы в новую папку в hdf. Как мне это сделать?

Ответы

Ответ 1

Я могу думать о достижении этого тремя способами.

  • Использование командной строки Linux

    Следующая команда работала для меня.

    hadoop fs -cat /tmp/Links.txt.gz | gzip -d | hadoop fs -put - /tmp/unzipped/Links.txt
    

    Мой gzipped файл 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 <gzipped file name>
    

    Например, когда я выполнил для моего gzipped файла:

    FileDecompressor /tmp/Links.txt.gz
    

    Я получил распакованный файл по адресу: /tmp/Links.txt

    Сохраняет распакованный файл в той же папке. Поэтому вам нужно изменить этот код, чтобы принять 2 входных параметра: <input file path> and <output folder>.

    Как только вы заработаете эту программу, вы можете написать оболочку /Perl/Python script для вызова этой программы для каждого из ваших входов.

  • Использование Pig script

    Вы можете написать простой Pig script, чтобы достичь этого.

    Я написал следующий script, который работает:

    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/
    

    Когда вы запускаете этот script, распакованное содержимое сохраняется во временной папке: /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 script, вам просто нужно позаботиться о параметризации имени файла (Links.txt.gz и Links.txt).

    Опять же, как только вы запустите этот script, вы можете написать оболочку /Perl/Python script для вызова этого Pig script для каждого из ваших входов.

Ответ 2

Bash solution

В моем случае я не хотел бы распаковывать файлы, поскольку я не был уверен в их содержании. Вместо этого я хотел убедиться, что все файлы в zip файлах будут извлечены на HDFS.

Я создал простой bash script. Комментарии должны дать вам понять, что происходит. Ниже приведено краткое описание.

#!/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 в temp dir (в файловой системе)
  • Распакуйте
  • Скопируйте все извлеченные файлы в каталог zip файла
  • Cleanup

Мне удалось заставить его работать с структурой sub-dir для многих zip файлов в каждом, используя /mypath/*/*.zip.

Удачи:)

Ответ 3

Вы можете сделать это, используя куст (при условии, что это текстовые данные).

create external table source (t str) location '<directory_with_gz_files>';
create external table target (t str) location '<target_dir>';
insert into table target select * from source;

Данные будут несжаты в новый набор файлов.

если вы не хотите изменять имена, и если у вас достаточно хранилища на node, где вы работаете, вы можете это сделать.

hadoop fs -get <your_source_directory> <directory_name>
It will create a directory where you run hadoop command. cd to it and gunzip all the files
cd ..
hadoop fs -moveFromLocal <directory_name> <target_hdfs_path>

Ответ 4

Если у вас сжатые текстовые файлы, hasoop fs -text поддерживает gzip вместе с другими распространенными форматами сжатия (snappy, lzo).

hadoop fs -text /tmp/a.gz | hadoop fs -put - /tmp/uncompressed_a

Ответ 5

Класс Hadoop FileUtil имеет unTar() и unZip() для достижения этого. Метод unTar() будет работать и с файлами .tar.gz и .tgz. К сожалению, они работают только с файлами локальной файловой системы. Вам придется использовать один из методов класса copy() для копирования в и из любых распределенных файловых систем, которые вам нужно использовать.