¿Cómo puedo descomprimir un .tar.gz en un solo paso (usando 7-Zip)?

82

Estoy usando 7-Zip en Windows XP y cada vez que descargo un archivo .tar.gz me lleva dos pasos extraer completamente los archivos.

  1. Hago clic derecho en el archivo example.tar.gz y elijo 7-Zip -> Extraer aquí del menú contextual.
  2. Luego tomo el archivo example.tar resultante y hago clic derecho nuevamente y elijo 7-Zip -> Extraer aquí del menú contextual.

¿Hay alguna manera a través del menú contextual para hacer esto en un solo paso?

quickcel
fuente

Respuestas:

46

Realmente no. Un archivo .tar.gz o .tgz realmente tiene dos formatos: .tares el archivo comprimido y .gzes la compresión. Entonces, el primer paso se descomprime, y el segundo paso extrae el archivo.

Para hacerlo todo en un solo paso, necesita el tarprograma. Cygwin incluye esto.

tar xzvf foobaz.tar.gz

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

También puede hacerlo "en un solo paso" abriendo el archivo en la GUI de 7 zip: abra el .tar.gzarchivo, haga doble clic en el .tararchivo incluido , luego extraiga esos archivos a la ubicación que elija.

Hay un largo hilo conductor aquí de gente que pregunta / voto para el manejo de un solo paso de archivos tgz y bz2. La falta de acción hasta el momento indica que no va a suceder hasta que alguien pise y contribuya significativamente (código, dinero, algo).

quijote curandero
fuente
70
Si 7zip fuera inteligente, lo haría en un solo paso por defecto, ya que el 99,99% del tiempo es lo que el usuario quiere hacer. De hecho, esta es la operación predeterminada de WinRar.
davr
66
@davr: 7-zip es un esfuerzo de código abierto; no dude en solicitar esta función. así es como funciona v4.65; No he probado los nuevos alpha v9.x, por lo que ya puede estar incluido.
quack quijote
Sí, esto es lo que extraño de la operación de WinRar. Podría confirmar que hasta hoy, octubre de 2012, 7zip todavía no se descomprime automáticamente con 1 paso. suspiro
fedmich
8
Tenga en cuenta que las instrucciones "en un paso" en realidad no lo hacen en un solo paso, en realidad descomprime el .gz en una carpeta temporal, luego abre el archivo .tar en 7-zip. Cuando los archivos son lo suficientemente pequeños, apenas se nota, pero es muy notable en archivos grandes. Solo pensé que merecía una aclaración.
Naasking
Hay una nueva respuesta con las instrucciones de un paso.
Barett
25

Antigua pregunta, pero estaba luchando con eso hoy, así que aquí está mi 2c. La herramienta de línea de comandos 7zip "7z.exe" (tengo instalada la v9.22) puede escribir en stdout y leer desde stdin para que pueda prescindir del archivo tar intermedio utilizando una tubería:

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

Dónde:

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

Consulte el archivo de ayuda (7-zip.chm) en el directorio de instalación para obtener más información sobre los comandos y modificadores de la línea de comandos.

Puede crear una entrada de menú contextual para archivos .tar.gz / .tgz que llame al comando anterior utilizando regedit o una herramienta de terceros como stexbar .

usuario2856
fuente
¿Qué hace el interruptor -aoa? No está listado en -? página
Superole
2
..ahh pero está en el archivo de ayuda; -ao [a | s | t | u] (modo de sobrescritura). por lo tanto: -aoa = sobrescribe todos los archivos existentes sin aviso
Superole
Buena respuesta pero OP no solicitó el bucle. ¡La respuesta de una línea de Joachim (similar) es genial y va al grano!
Jason
@ Jason esa respuesta es exactamente la misma que mi respuesta SO stackoverflow.com/a/14699663/737471 Puedo editar esta ...
user2856
9

Comenzando con 7-zip 9.04, hay una opción de línea de comandos para hacer la extracción combinada sin usar almacenamiento intermedio para el .tararchivo plano :

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

-tgzipes necesario si se nombra el archivo de entrada en .tgzlugar de .tar.gz.

Joachim Sauer
fuente
2
¿Alguna forma de obtener eso en el menú contextual del Explorador de Windows 10?
Brian Leishman
4

Está utilizando Windows XP, por lo que debería tener instalado Windows Scripting Host de manera predeterminada. Dicho esto, aquí hay un script WSH JScript para hacer lo que necesita. Simplemente copie el código a un nombre de archivo xtract.bat o algo por el estilo (puede ser lo que sea, siempre que tenga la extensión .bat), y ejecute:

xtract.bat example.tar.gz

Por defecto, el script verificará la carpeta del script, así como la PATHvariable de entorno de su sistema para 7z.exe. Si desea cambiar el aspecto de las cosas, puede cambiar la variable SevenZipExe en la parte superior del script a lo que quiera que sea el nombre ejecutable. (Por ejemplo, 7za.exe o 7z-real.exe) También puede establecer un directorio predeterminado para el ejecutable cambiando SevenZipDir. Entonces, si 7z.exees así C:\Windows\system32\7z.exe, pondrías:

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

De todos modos, aquí está el script:

@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);
Charles Grunwald
fuente
No que yo supiese. Inicialmente lo encontré en el siguiente repositorio de origen: github.com/ynkdir/winscript Funciona, porque el motor WSH jscript aparentemente ignora el primer bit, hasta que comienza el comentario. Se puede encontrar más información en: stackoverflow.com/questions/4999395/…
Charles Grunwald
Encontré esto: javascriptkit.com/javatutors/conditionalcompile2.shtml que parece indicar que @set @var = valuees una sintaxis JScript para declarar variables en tiempo de compilación. Por lo tanto, es JScript válido y un comando CMD
hdgarrood
2

Como puede ver, 7-Zip no es muy bueno en esto. La gente ha estado pidiendo operaciones atómicas de tarball desde 2009. Aquí hay un pequeño programa (490 KB) en Go que puede hacerlo, lo compilé para usted.

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)
    }
  }
}
Steven Penny
fuente
1

A partir de Windows 10, compilación 17063, tary curlson compatibles, por lo tanto, es posible descomprimir un archivo .tar.gz en un solo paso utilizando el tarcomando, como se muestra a continuación.

tar -xzvf your_archive.tar.gz

Escriba tar --helppara obtener más información sobre tar.

Juniver Hazoic
fuente
alquitrán, rizo, ssh, sftp, pegado de rmb y pantalla más ancha. Los usuarios están mimados y podridos.
mckenzm
0

7za funciona correctamente como se muestra a continuación:

7za.exe x D:\pkg-temp\Prod-Rtx-Service.tgz -so | 7za.exe x -si -ttar -oD:\pkg-temp\Prod-Rtx-Service
Alan Hu
fuente
3
¿Puedes agregar algún contexto sobre cómo funciona este comando? Consulte Cómo responder y realice nuestro recorrido .
Burgi