題 如何一步解壓縮.tar.gz(使用7-Zip)?


我在Windows XP上使用7-Zip,每當我下載.tar.gz文件時,我需要兩個步驟來完全提取文件。

  1. 我右鍵點擊了 example.tar.gz 文件並選擇 7-Zip - > Extract Here 從上下文菜單中。
  2. 然後我拿出結果 example.tar 文件並再次右鍵單擊並選擇 7-Zip - > Extract Here 從上下文菜單中。

有沒有辦法通過上下文菜單一步完成?


75
2017-12-07 20:01


起源




答案:


並不是的。 .tar.gz或.tgz文件確實有兩種格式: .tar 是檔案,和 .gz 是壓縮。所以第一步解壓縮,第二步提取存檔。

要一步到位,你需要的 tar 程序。 Cygwin的 包括這個。

tar xzvf foobaz.tar.gz

; x = eXtract 
; z = filter through gZip
; v = be Verbose (show activity)
; f = filename

您也可以通過在7-zip GUI中打開文件“一步到位”來執行此操作:打開 .tar.gz 文件,雙擊包含 .tar 文件,然後將這些文件解壓縮到您選擇的位置。

有一個長期運行的線程 這裡 人們要求/投票一步處理tgz和bz2文件。迄今為止缺乏行動表明,除非有人採取行動並做出有意義的貢獻(代碼,金錢,某些事情),否則不會發生這種情況。


42
2017-12-07 20:07



如果7zip很聰明,默認情況下會一步完成,因為99.99%的時間是用戶想要做的。實際上,這是WinRar的默認操作。 - davr
@davr:7-zip是一個開源的努力;隨意請求此功能。這就是v4.65的運作方式;我沒有嘗試過較新的v9.x alphas,所以它可能已經包含在內。 - quack quixote
是的,這是我從WinRar的操作中錯過的。我可以確認,截至今天,2012年10月,7zip仍然沒有自動減壓1步。嘆 - fedmich
請注意,“一步到位”指令實際上並不是一步完成,它實際上將.gz解壓縮到一個臨時文件夾中,然後以7-zip打開.tar文件。當檔案足夠小時,它幾乎不可察覺,但在大型檔案中卻非常明顯。只是認為值得澄清。 - naasking
一步說明有一個新的答案。 - Barett


老問題,但今天我正在努力,所以這是我的2c。 7zip命令行工具“7z.exe”(我安裝了v9.22)可以寫入stdout並從stdin讀取,因此你可以通過使用管道來完成沒有中間tar文件:

7z x "somename.tar.gz" -so | 7z x -aoa -si -ttar -o"somename"

哪裡:

x     = Extract with full paths command
-so   = write to stdout switch
-si   = read from stdin switch
-aoa  = Overwrite all existing files without prompt.
-ttar = Treat the stdin byte stream as a TAR file
-o    = output directory

有關命令行命令和開關的詳細信息,請參閱安裝目錄中的幫助文件(7-zip.chm)。

您可以為.tar.gz / .tgz文件創建上下文菜單條目,使用regedit或第三方工具調用上述命令 stexbar


19
2018-02-05 02:07



-aoa開關做什麼?它沒有列在 - ?頁 - Superole
..ahh但它在幫助文件中; -ao [a | s | t | u](覆蓋模式)。因此:-aoa =覆蓋所有現有文件沒有提示 - Superole
很好的答案,但OP沒有要求循環。 Joachim的(類似的)單行答案非常棒而且非常重要! - Jason
@Jason答案與我的答案完全一樣 stackoverflow.com/a/14699663/737471 我可能只是編輯這個...... - Luke


從7-zip 9.04開始,有一個命令行選項可以在不使用普通的中間存儲的情況下進行組合提取 .tar 文件:

7z x -tgzip -so theinputfile.tgz | 7z x -si -ttar

-tgzip 如果輸入文件已命名,則需要 .tgz 代替 .tar.gz


5
2018-01-07 20:23



有沒有辦法進入Windows 10資源管理器上下文菜單? - Brian Leishman


您使用的是Windows XP,因此默認情況下應安裝Windows Scripting Host。話雖如此,這是一個WSH JScript腳本,可以滿足您的需求。只需將代碼複製到文件名即可 xtract.bat 或者沿著那些方向的東西(可以是任何東西,只要它有擴展名 .bat),並運行:

xtract.bat example.tar.gz

默認情況下,腳本將檢查腳本的文件夾以及系統的文件夾 PATH 7z.exe的環境變量。如果要更改查找內容的方式,可以將腳本頂部的SevenZipExe變量更改為您想要的可執行文件名。 (例如,7za.exe或7z-real.exe)您還可以通過更改SevenZipDir為可執行文件設置默認目錄。因此,如果 7z.exe 在 C:\Windows\system32\7z.exe你會說:

var SevenZipDir = "C:\\Windows\\system32";

無論如何,這是腳本:

@set @junk=1 /* vim:set ft=javascript:
@echo off
cscript //nologo //e:jscript "%~dpn0.bat" %*
goto :eof
*/
/* Settings */
var SevenZipDir = undefined;
var SevenZipExe = "7z.exe";
var ArchiveExts = ["zip", "tar", "gz", "bzip", "bz", "tgz", "z", "7z", "bz2", "rar"]

/* Multi-use instances */
var WSH = new ActiveXObject("WScript.Shell");
var FSO = new ActiveXObject("Scripting.FileSystemObject");
var __file__ = WScript.ScriptFullName;
var __dir__ = FSO.GetParentFolderName(__file__);
var PWD = WSH.CurrentDirectory;

/* Prototypes */
(function(obj) {
    obj.has = function object_has(key) {
        return defined(this[key]);
    };
    return obj;
})(this.Object.prototype);

(function(str) {
    str.trim = function str_trim() {
        return this.replace(/^\s\s*/, '').replace(/\s\s*$/, '');
    };
})(this.String.prototype);

(function(arr) {
    arr.contains = function arr_contains(needle) {
        for (var i in this) {
            if (this[i] == needle) {
                return true;
            }
        }
        return false;
    }
})(this.Array.prototype);

/* Utility functions */
function defined(obj)
{
    return typeof(obj) != "undefined";
}

function emptyStr(obj)
{
    return !(defined(obj) && String(obj).length);
}

/* WSH-specific Utility Functions */
function echo()
{
    if(!arguments.length) return;
    var msg = "";
    for (var n = 0; n < arguments.length; n++) {
        msg += arguments[n];
        msg += " ";
    }
    if(!emptyStr(msg))
        WScript.Echo(msg);
}

function fatal(msg)
{
    echo("Fatal Error:", msg);
    WScript.Quit(1);
}

function findExecutable()
{
    // This function searches the directories in;
    // the PATH array for the specified file name;
    var dirTest = emptyStr(SevenZipDir) ? __dir__ : SevenZipDir;
    var exec = SevenZipExe;
    var strTestPath = FSO.BuildPath(dirTest, exec);
    if (FSO.FileExists(strTestPath))
        return FSO.GetAbsolutePathName(strTestPath);

    var arrPath = String(
            dirTest + ";" + 
            WSH.ExpandEnvironmentStrings("%PATH%")
        ).split(";");

    for(var i in arrPath) {
        // Skip empty directory values, caused by the PATH;
        // variable being terminated with a semicolon;
        if (arrPath[i] == "")
            continue;

        // Build a fully qualified path of the file to test for;
        strTestPath = FSO.BuildPath(arrPath[i], exec);

        // Check if (that file exists;
        if (FSO.FileExists(strTestPath))
            return FSO.GetAbsolutePathName(strTestPath);
    }
    return "";
}

function readall(oExec)
{
    if (!oExec.StdOut.AtEndOfStream)
      return oExec.StdOut.ReadAll();

    if (!oExec.StdErr.AtEndOfStream)
      return oExec.StdErr.ReadAll();

    return -1;
}

function xtract(exec, archive)
{
    var splitExt = /^(.+)\.(\w+)$/;
    var strTmp = FSO.GetFileName(archive);
    WSH.CurrentDirectory = FSO.GetParentFolderName(archive);
    while(true) {
        var pathParts = splitExt.exec(strTmp);
        if(!pathParts) {
            echo("No extension detected for", strTmp + ".", "Skipping..");
            break;
        }

        var ext = pathParts[2].toLowerCase();
        if(!ArchiveExts.contains(ext)) {
            echo("Extension", ext, "not recognized. Skipping.");
            break;
        }

        echo("Extracting", strTmp + "..");
        var oExec = WSH.Exec('"' + exec + '" x -bd "' + strTmp + '"');
        var allInput = "";
        var tryCount = 0;

        while (true)
        {
            var input = readall(oExec);
            if (-1 == input) {
                if (tryCount++ > 10 && oExec.Status == 1)
                    break;
                WScript.Sleep(100);
             } else {
                  allInput += input;
                  tryCount = 0;
            }
        }

        if(oExec. ExitCode!= 0) {
            echo("Non-zero return code detected.");
            break;
        }

        WScript.Echo(allInput);

        strTmp = pathParts[1];
        if(!FSO.FileExists(strTmp))
            break;
    }
    WSH.CurrentDirectory = PWD;
}

function printUsage()
{
    echo("Usage:\r\n", __file__, "archive1 [archive2] ...");
    WScript.Quit(0);
}

function main(args)
{
    var exe = findExecutable();
    if(emptyStr(exe))
        fatal("Could not find 7zip executable.");

    if(!args.length || args(0) == "-h" || args(0) == "--help" || args(0) == "/?")
        printUsage();

    for (var i = 0; i < args.length; i++) {
        var archive = FSO.GetAbsolutePathName(args(i));
        if(!FSO.FileExists(archive)) {
            echo("File", archive, "does not exist. Skipping..");
            continue;
        }
        xtract(exe, archive);
    }
    echo("\r\nDone.");
}

main(WScript.Arguments.Unnamed);

4
2017-11-26 05:34



不是我知道的。我最初在以下源代碼庫中找到它: github.com/ynkdir/winscript 它有效,因為WSH jscript引擎顯然忽略了第一位,直到評論開始。更多信息可在以下網址找到: stackoverflow.com/questions/4999395/... - Charles Grunwald
發現了這個: javascriptkit.com/javatutors/conditionalcompile2.shtml 這似乎表明了這一點 @set @var = value 是用於聲明編譯時變量的JScript語法。所以這是有效的JScript和CMD命令 - hdgarrood


正如你所看到的,7-Zip並不是很擅長這一點。人們一直都是 要求自2009年以來的tarball原子操作。 這是一個小程序 (490 KB)在Go中可以做到,我 編譯它 為了你。

package main
import (
  "archive/tar"
  "compress/gzip"
  "flag"
  "fmt"
  "io"
  "os"
  "strings"
 )

func main() {
  flag.Parse() // get the arguments from command line
  sourcefile := flag.Arg(0)
  if sourcefile == "" {
    fmt.Println("Usage : go-untar sourcefile.tar.gz")
    os.Exit(1)
  }
  file, err := os.Open(sourcefile)
  if err != nil {
    fmt.Println(err)
    os.Exit(1)
  }
  defer file.Close()
  var fileReader io.ReadCloser = file
  // just in case we are reading a tar.gz file,
  // add a filter to handle gzipped file
  if strings.HasSuffix(sourcefile, ".gz") {
    if fileReader, err = gzip.NewReader(file); err != nil {
      fmt.Println(err)
      os.Exit(1)
    }
    defer fileReader.Close()
  }
  tarBallReader := tar.NewReader(fileReader)
  // Extracting tarred files
  for {
    header, err := tarBallReader.Next()
    if err != nil {
      if err == io.EOF {
        break
      }
      fmt.Println(err)
      os.Exit(1)
    }
    // get the individual filename and extract to the current directory
    filename := header.Name
    switch header.Typeflag {
    case tar.TypeDir:
      // handle directory
      fmt.Println("Creating directory :", filename)
      // or use 0755 if you prefer
      err = os.MkdirAll(filename, os.FileMode(header.Mode))
      if err != nil {
        fmt.Println(err)
        os.Exit(1)
      }
    case tar.TypeReg:
      // handle normal file
      fmt.Println("Untarring :", filename)
      writer, err := os.Create(filename)
      if err != nil {
        fmt.Println(err)
        os.Exit(1)
      }
      io.Copy(writer, tarBallReader)
      err = os.Chmod(filename, os.FileMode(header.Mode))
      if err != nil {
        fmt.Println(err)
        os.Exit(1)
      }
      writer.Close()
    default:
      fmt.Printf("Unable to untar type : %c in file %s", header.Typeflag,
      filename)
    }
  }
}

2
2017-10-29 18:37





7za正常工作如下:

7za.exe x D:\pkg-temp\Prod-Rtx-Service.tgz -so | 7za.exe x -si -ttar -oD:\pkg-temp\Prod-Rtx-Service

0
2017-08-31 08:08



你能為這個命令的工作原理添加一些上下文嗎?請參閱 怎麼回答 拿走我們的 遊覽。 - Burgi