2011-06-10 33 views
4

我的Ubuntu網絡服務器上有大量gzip壓縮文件,我需要將它們轉換爲zip文件。我認爲這將通過腳本完成,但我應該使用哪種語言,以及如何解壓縮和重新分區文件?將tar.gz轉換爲zip

回答

2

一個簡單的bash腳本將是最簡單的,當然?這樣您就可以調用tarzip命令。

6

我會用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)。請注意,這會破壞很多目錄,因此請確保在執行此操作之前知道它的作用。

有關${foo%bar}語法的更多詳細信息,請參閱the bash(1) reference card

+0

這基本上是我所建議的,但你在比我掀起了一個例子更快。 :) – Sven 2011-06-10 04:24:19

+0

@Sven,不費心測試是削減那些分鐘的好方法。 :) – sarnold 2011-06-10 04:26:15

0

您可以使用node.jstar-to-zip用於這一目的。所有你需要做的是:

如果你沒有它,安裝node.js與nvm

然後安裝tar-to-zip有:

npm i tar-to-zip -g 

並使用它:

tarzip *.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); 
} 
0

Zipfiles是方便,因爲他們提供的文件隨機訪問。 Tar文件只有順序。

我對這種轉換的解決方案是這個shell腳本,它通過tar(1)「--to-command」選項調用它自己。 (我更喜歡這個,而不是有兩個腳本)。但我承認「untar和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 "@ -\[email protected]=$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 
0

這裏是在此基礎上answer here一個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)