将 tar.gz 转换为 zip

发布于 2024-11-14 22:49:28 字数 92 浏览 2 评论 0原文

我的 Ubuntu 网络服务器上有大量 gzip 压缩档案,我需要将它们转换为 zip。我认为这可以通过脚本来完成,但是我应该使用什么语言,以及如何解压缩和重新压缩文件?

I've got a large collection of gzipped archives on my Ubuntu webserver, and I need them converted to zips. I figure this would be done with a script, but what language should I use, and how would I go about unzipping and rezipping files?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(7

梨涡 2024-11-21 22:49:28

我会用 bash(1) 一句台词来完成它:

for f in *.tar.gz;\
do rm -rf ${f%.tar.gz} ;\
mkdir ${f%.tar.gz} ;\
tar -C ${f%.tar.gz} zxvf $f ;\
zip -r ${f%.tar.gz} $f.zip ;\
rm -rf ${f%.tar.gz} ;\
done

这不是很漂亮,因为我不太擅长 bash(1)。请注意,这会破坏很多目录,因此在执行此操作之前请确保您知道它的作用。

请参阅bash(1) 参考卡有关 ${foo%bar} 语法的更多详细信息。

I'd do it with a bash(1) one-liner:

for f in *.tar.gz;\
do rm -rf ${f%.tar.gz} ;\
mkdir ${f%.tar.gz} ;\
tar -C ${f%.tar.gz} zxvf $f ;\
zip -r ${f%.tar.gz} $f.zip ;\
rm -rf ${f%.tar.gz} ;\
done

It isn't very pretty because I'm not great at bash(1). Note that this destroys a lot of directories so be sure you know what this does before doing it.

See the bash(1) reference card for more details on the ${foo%bar} syntax.

飘落散花 2024-11-21 22:49:28

一个简单的 bash 脚本肯定是最简单的吧?这样您就可以调用 tarzip 命令。

A simple bash script would be easiest, surely? That way you can just invoke the tar and zip commands.

走野 2024-11-21 22:49:28

Unix 平台上最简单的解决方案很可能是使用 fusion 和类似 archivemount (libarchive) 的东西, http://en .wikipedia.org/wiki/Archivemount

/iaw

the easiest solution on unix platforms may well be to use fuse and something like archivemount (libarchive), http://en.wikipedia.org/wiki/Archivemount .

/iaw

倒带 2024-11-21 22:49:28

您可以使用 node.jstar-to-zip 用于此目的。您需要做的就是:

使用 nvm 安装node.js(如果您没有)。

然后使用以下命令安装 tar-to-zip

npm i tar-to-zip -g

并使用它:

tar-to-zip *.tar.gz

您还可以通过编程方式将 .tar.gz 文件转换为 .zip
您应该在本地安装 asynctar-to-zip

npm i async tar-to-zip

然后使用以下内容创建 converter.js

#!/usr/bin/env node

'use strict';

const fs = require('fs');
const tarToZip = require('tar-to-zip');
const eachSeries = require('async/eachSeries');
const names = process.argv.slice(2);

eachSeries(names, convert, exitIfError);

function convert(name, done) {
    const {stdout} = process;
    const onProgress = (n) => {
        stdout.write(`\r${n}%: ${name}`);
    };
    const onFinish = (e) => {
        stdout.write('\n');
        done();
    };

    const nameZip = name.replace(/\.tar\.gz$/, '.zip');    
    const zip = fs.createWriteStream(nameZip)
        .on('error', (error) => {
            exitIfError(error);
            fs.unlinkSync(zipPath);
        });

    const progress = true;
    tarToZip(name, {progress})
        .on('progress', onProgress)
        .on('error', exitIfError)
        .getStream()
        .pipe(zip)
        .on('finish', onFinish);
}

function exitIfError(error) {
    if (!error)
        return;

    console.error(error.message);
    process.exit(1);
}

You can use node.js and tar-to-zip for this purpose. All you need to do is:

Install node.js with nvm if you do not have it.

And then install tar-to-zip with:

npm i tar-to-zip -g

And use it with:

tar-to-zip *.tar.gz

Also you can convert .tar.gz files to .zip programmatically.
You should install async and tar-to-zip locally:

npm i async tar-to-zip

And then create converter.js with contents:

#!/usr/bin/env node

'use strict';

const fs = require('fs');
const tarToZip = require('tar-to-zip');
const eachSeries = require('async/eachSeries');
const names = process.argv.slice(2);

eachSeries(names, convert, exitIfError);

function convert(name, done) {
    const {stdout} = process;
    const onProgress = (n) => {
        stdout.write(`\r${n}%: ${name}`);
    };
    const onFinish = (e) => {
        stdout.write('\n');
        done();
    };

    const nameZip = name.replace(/\.tar\.gz$/, '.zip');    
    const zip = fs.createWriteStream(nameZip)
        .on('error', (error) => {
            exitIfError(error);
            fs.unlinkSync(zipPath);
        });

    const progress = true;
    tarToZip(name, {progress})
        .on('progress', onProgress)
        .on('error', exitIfError)
        .getStream()
        .pipe(zip)
        .on('finish', onFinish);
}

function exitIfError(error) {
    if (!error)
        return;

    console.error(error.message);
    process.exit(1);
}
你是暖光i 2024-11-21 22:49:28

Zip 文件很方便,因为它们提供对文件的随机访问。 Tar 文件仅是连续的。

我对此转换的解决方案是这个 shell 脚本,它通过 tar(1)“--to-command”选项调用自身。 (我更喜欢这样而不是有两个脚本)。但我承认“untar and zip -r”比这更快,因为不幸的是 zipnote(1) 无法就地工作。

#!/bin/zsh -feu

## Convert a tar file into zip:

usage() {
    setopt POSIX_ARGZERO
    cat <<EOF
    usage: ${0##*/} [+-h] [-v] [--] {tarfile} {zipfile}"

-v verbose
-h print this message
converts the TAR archive into ZIP archive.
EOF
    unsetopt POSIX_ARGZERO
}

while getopts :hv OPT; do
    case $OPT in
        h|+h)
            usage
            exit
            ;;
        v)
            # todo: ignore TAR_VERBOSE from env?
            # Pass to the grand-child process:
            export TAR_VERBOSE=y
            ;;
        *)
            usage >&2
            exit 2
    esac
done
shift OPTIND-1
OPTIND=1

# when invoked w/o parameters:
if [ $# = 0 ] # todo: or stdin is not terminal
then
    # we are invoked by tar(1)
    if [ -n "${TAR_VERBOSE-}" ]; then echo $TAR_REALNAME >&2;fi
    zip --grow --quiet $ZIPFILE -
    # And rename it:
    # fixme: this still makes a full copy, so slow.
    printf "@ -\n@=$TAR_REALNAME\n" | zipnote -w $ZIPFILE
else
    if [ $# != 2 ]; then usage >&2; exit 1;fi
    # possibly: rm -f $ZIPFILE
    ZIPFILE=$2 tar -xaf $1 --to-command=$0
fi

Zipfiles are handy because they offer random access to files. Tar files only sequential.

My solution for this conversion is this shell script, which calls itself via tar(1) "--to-command" option. (I prefer that rather than having 2 scripts). But I admit "untar and zip -r" is faster than this, because zipnote(1) cannot work in-place, unfortunately.

#!/bin/zsh -feu

## Convert a tar file into zip:

usage() {
    setopt POSIX_ARGZERO
    cat <<EOF
    usage: ${0##*/} [+-h] [-v] [--] {tarfile} {zipfile}"

-v verbose
-h print this message
converts the TAR archive into ZIP archive.
EOF
    unsetopt POSIX_ARGZERO
}

while getopts :hv OPT; do
    case $OPT in
        h|+h)
            usage
            exit
            ;;
        v)
            # todo: ignore TAR_VERBOSE from env?
            # Pass to the grand-child process:
            export TAR_VERBOSE=y
            ;;
        *)
            usage >&2
            exit 2
    esac
done
shift OPTIND-1
OPTIND=1

# when invoked w/o parameters:
if [ $# = 0 ] # todo: or stdin is not terminal
then
    # we are invoked by tar(1)
    if [ -n "${TAR_VERBOSE-}" ]; then echo $TAR_REALNAME >&2;fi
    zip --grow --quiet $ZIPFILE -
    # And rename it:
    # fixme: this still makes a full copy, so slow.
    printf "@ -\n@=$TAR_REALNAME\n" | zipnote -w $ZIPFILE
else
    if [ $# != 2 ]; then usage >&2; exit 1;fi
    # possibly: rm -f $ZIPFILE
    ZIPFILE=$2 tar -xaf $1 --to-command=$0
fi
千寻… 2024-11-21 22:49:28

这是一个基于此处答案的Python解决方案:

import sys, tarfile, zipfile, glob

def convert_one_archive(file_name):
    out_file = file_name.replace('.tar.gz', '.zip')
    with tarfile.open(file_name, mode='r:gz') as tf:
        with zipfile.ZipFile(out_file, mode='a', compression=zipfile.ZIP_DEFLATED) as zf:
            for m in tf.getmembers():
                f = tf.extractfile( m )
                fl = f.read()
                fn = m.name
                zf.writestr(fn, fl)

for f in glob.glob('*.tar.gz'):
    convert_one_archive(f)

Here is a python solution based on this answer here:

import sys, tarfile, zipfile, glob

def convert_one_archive(file_name):
    out_file = file_name.replace('.tar.gz', '.zip')
    with tarfile.open(file_name, mode='r:gz') as tf:
        with zipfile.ZipFile(out_file, mode='a', compression=zipfile.ZIP_DEFLATED) as zf:
            for m in tf.getmembers():
                f = tf.extractfile( m )
                fl = f.read()
                fn = m.name
                zf.writestr(fn, fl)

for f in glob.glob('*.tar.gz'):
    convert_one_archive(f)
余厌 2024-11-21 22:49:28

这是基于 @Brad Campbell 的答案的脚本,它适用于作为命令参数传递的文件,适用于其他 tar 文件类型(未压缩或 tarfile 支持的其他压缩类型),并处理源 tar 文件中的目录。如果源文件包含符号链接或硬链接,它还会打印警告,并将其转换为常规文件。对于符号链接,链接在转换期间解析。如果链接目标不在 tar 中,这可能会导致错误;从安全角度来看,这也存在潜在危险,因此用户要小心。

#!/usr/bin/python

import sys, tarfile, zipfile, glob, re

def convert_one_archive(in_file, out_file):
    with tarfile.open(in_file, mode='r:*') as tf:
        with zipfile.ZipFile(out_file, mode='a', compression=zipfile.ZIP_DEFLATED) as zf:
            for m in [m for m in tf.getmembers() if not m.isdir()]:
                if m.issym() or m.islnk():
                    print('warning: symlink or hardlink converted to file')
                f = tf.extractfile(m)
                fl = f.read()
                fn = m.name
                zf.writestr(fn, fl)

for in_file in sys.argv[1:]:
    out_file = re.sub(r'\.((tar(\.(gz|bz2|xz))?)|tgz|tbz|tbz2|txz)
, '.zip', in_file)
    if out_file == in_file:
        print(in_file, '---> [skipped]')
    else:
        print(in_file, '--->', out_file)
        convert_one_archive(in_file, out_file)

Here is script based on @Brad Campbell's answer that works on files passed as command arguments, works with other tar file types (uncompressed or the other compression types supported by tarfile), and handles directories in the source tar file. It will also print warnings if the source file contains a symlink or hardlink, which are converted to regular files. For symlinks, the link is resolved during conversion. This can lead to an error if the link target is not in the tar; this is also potentially dangerous from a security standpoint, so user beware.

#!/usr/bin/python

import sys, tarfile, zipfile, glob, re

def convert_one_archive(in_file, out_file):
    with tarfile.open(in_file, mode='r:*') as tf:
        with zipfile.ZipFile(out_file, mode='a', compression=zipfile.ZIP_DEFLATED) as zf:
            for m in [m for m in tf.getmembers() if not m.isdir()]:
                if m.issym() or m.islnk():
                    print('warning: symlink or hardlink converted to file')
                f = tf.extractfile(m)
                fl = f.read()
                fn = m.name
                zf.writestr(fn, fl)

for in_file in sys.argv[1:]:
    out_file = re.sub(r'\.((tar(\.(gz|bz2|xz))?)|tgz|tbz|tbz2|txz)
, '.zip', in_file)
    if out_file == in_file:
        print(in_file, '---> [skipped]')
    else:
        print(in_file, '--->', out_file)
        convert_one_archive(in_file, out_file)
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文