Python: извлекайте файлы gz с исходными именами и расширениями файлов и соблюдайте их.

В папке у меня есть много файлов .gz, и в этих файлах gz некоторые из них имеют расширение .txt, некоторые — .csv, некоторые — .xml или некоторые другие расширения.

Например. gz (исходный/сжатый файл в()) файлы в папке будут

C:\Xiang\filename1.txt.gz (filename1.txt)
C:\Xiang\filename2.txt.gz (filename2.txt)
C:\Xiang\some_prefix_filename3.txt.gz (filename3.txt)
...
C:\Xiang\xmlfile1.xml_some_postfix.gz   (xmlfile1.xml)
C:\Xiang\yyyymmddxmlfile2.xml.gz       (xmlfile2.xml)
...
C:\Xiang\someotherName.csv.gz            (someotherName.csv)
C:\Xiang\possiblePrefixsomeotherfile1.someotherExtension.gz (someotherfile1.someotherExtension)
C:\Xiang\someotherfile2.someotherExtensionPossiblePostfix.gz (someotherfile2.someotherExtension)
...

Как я мог просто заархивировать все файлы .gz в Python в Windows 10 в папке C:\Xiang и сохранить в папку C:\UnZipGz, соблюдая исходные имена файлов, с результатом следующим образом:

C:\UnZipGz\filename1.txt
C:\UnZipGz\filename2.txt
C:\UnZipGz\filename3.txt
...
C:\UnZipGz\xmlfile1.xml.
C:\UnZipGz\xmlfile2.xml.
...
C:\UnZipGz\someotherName.csv.
C:\UnZipGz\someotherfile1.someotherExtension
C:\UnZipGz\someotherfile2.someotherExtension
...

Как правило, соглашение об именах файлов gz соответствует именам файлов внутри, но это не всегда так. Каким-то образом в прошлом происходило переименование некоторых файлов .gz. Теперь имена файлов gz не обязательно совпадают с именами файлов в файлах gz.

Как я могу извлечь все файлы gz и сохранить исходные имена файлов и расширения. То есть, независимо от того, как называются gz-файлы, при извлечении gz-файлов сохраняйте только распакованные файлы в исходном формате как

filename.fileExtension

в папку C:\UnZipGz.


person Yu Xiang    schedule 11.02.2021    source источник
comment
В Linux использование команды gunzip -N может учитывать исходное имя файла. Кто-нибудь знает, как это сделать в Windows cmd или в коде Python? См. сообщение: superuser.com/questions/859785/   -  person Yu Xiang    schedule 11.02.2021
comment
Используйте github.com/PierreSelim/gzinfo, см. мой обновленный ответ   -  person D Hudson    schedule 11.02.2021
comment
@D Хадсон, супер! Большое спасибо.   -  person Yu Xiang    schedule 11.02.2021
comment
Без проблем. Если мои ответы решили вашу проблему, примите это. Большое спасибо   -  person D Hudson    schedule 12.02.2021


Ответы (1)


import gzip
import os


INPUT_DIRECTORY = 'C:\Xiang'
OUTPUT_DIRECTORY = 'C:\UnZipGz'
GZIP_EXTENSION = '.gz'


def make_output_path(output_directory, zipped_name):
    """ Generate a path to write the unzipped file to.

    :param str output_directory: Directory to place the file in
    :param str zipped_name: Name of the zipped file
    :return str:
    """
    name_without_gzip_extension = zipped_name[:-len(GZIP_EXTENSION)]
    return os.path.join(output_directory, name_without_gzip_extension)


for file in os.scandir(INPUT_DIRECTORY):
    if not file.name.lower().endswith(GZIP_EXTENSION):
        continue

    output_path = make_output_path(OUTPUT_DIRECTORY, file.name)

    print('Decompressing', file.path, 'to', output_path)

    with gzip.open(file.path, 'rb') as file:
        with open(output_path, 'wb') as output_file:
            output_file.write(file.read())

Объяснение:

  1. Перебрать все файлы в папке с соответствующим расширением.
  2. Создайте путь к новому каталогу без расширения gzip.
  3. Откройте файл и запишите его распакованное содержимое по новому пути.

Чтобы получить исходное имя файла, вы можете использовать gzinfo: https://github.com/PierreSelim/gzinfo

>>> import gzinfo
>>> info = gzinfo.read_gz_info('bar.txt.gz')
>>> info.fname
'foo.txt'

Ссылки для извлечения исходного имени файла:

person D Hudson    schedule 11.02.2021
comment
@D Хадсон, спасибо за ответ, это работает с моим случаем. Но возможно ли, что имя файла .gz не соответствует имени файла внутри? Я обновил свой вопрос. - person Yu Xiang; 11.02.2021
comment
Сжатый файл не является архивом. Он не содержит других файлов или имен файлов: это всего лишь один файл, сжатый с помощью алгоритма gzip. Чтобы создать архив, сжатый с помощью gzip, обычно используется пара gzip с tar. - person D Hudson; 11.02.2021
comment
@D Хадсон, спасибо! Вы имеете в виду, что имена файлов gz всегда будут соответствовать именам файлов базовых файлов. Если это так, ваш код решает мою проблему. Я был немного обеспокоен тем, что имена файлов базовых файлов могут отличаться от имен файлов gz. - person Yu Xiang; 11.02.2021
comment
Это только соглашение, что сжатое имя совпадает с исходным файлом + '.gz'. Оригинальный файл мог называться как угодно. Однако сам сжатый файл не сохраняет запись исходного имени файла. - person D Hudson; 11.02.2021
comment
@D Хадсон, в данном случае. Приведенного выше решения будет недостаточно, так как я хотел бы извлечь файл gz и сохранить распакованный файл с исходным именем. Например. исходный файл example1.txt, gz файл создается как example1.txt.gz, но потом каким-то образом переименовывается в 20200211_example1.txt.gz (но внутри файл все равно example1.txt). Ваш код сохранит его 20200211_example1.txt в выходной папке. Однако то, что я хочу, это example1.txt в выходной папке. - person Yu Xiang; 11.02.2021
comment
Файл gzip не хранит имя исходного файла, поэтому вам потребуется сопоставление между именем сжатого файла и именем, которое вы хотите использовать для распакованного файла. Например: {"20200211_example1.txt.gz": "example1.txt"} это можно использовать для поиска нужного имени. - person D Hudson; 11.02.2021
comment
это будет сложно, так как в папке тысячи мелких файлов, и некоторые с префиксом/постфиксом, а некоторые нет. Это сопоставление трудно решить, потому что трудно определить, какая часть является префиксом/постфиксом (если есть), а какая часть принадлежит исходному имени файла. - person Yu Xiang; 11.02.2021
comment
Давайте продолжим обсуждение в чате. - person Yu Xiang; 11.02.2021
comment
@Д Хадсон. Поскольку я могу использовать 7-zip для архивирования файла test.gz, а исходный файл с originalFileName.txt сохраняется в папке un-zip ./test. Это означает, что информация об исходном имени файла не теряется. Возможно, в настоящее время это невозможно с использованием пакета Python gzip, но это не значит, что это невозможно. Я постараюсь выяснить, возможно ли это с помощью другого языка программирования/пакета, и держать вас в курсе. - person Yu Xiang; 11.02.2021
comment
@DHudson gzip может вести внутреннюю запись исходного имени файла (ищите ссылки на FNAME в RFC1952). Если вы используете gunzip для распаковки gzip-файла, параметр -N восстановит исходное имя файла. - person pmqs; 12.02.2021