Script zum entpacken von Archiven unter Linux

Stellt hier eure Projekte vor.
Internetseiten, Skripte, und alles andere bzgl. Python.
Antworten
bennym
User
Beiträge: 36
Registriert: Freitag 13. Oktober 2006, 21:17
Kontaktdaten:

Hallo!

Nachdem ich mich in optparse eingearbeitet habe und von euch ein paar Fragen super beantwortet kam, möchte ich euch mein neustes Script zeigen.

Das Script kann die gewöhnlichen Archive unter linux sehr einfach entpacken, und hilft mir, weil ich nicht die ganzen Befehl im Kopf habe um alle möglichen Archive zu entpacken.

Ich würde mich über Anregungen und Tipps freuen!:D

Danke!

mfg benny

Code: Alles auswählen

#!/usr/bin/python
# -*-coding=utf-8 -*-

from optparse import OptionParser
import os, sys

#Endung:Enpackbefehl+Leerzeichen
befehl = {"tar":"tar xfv ", "gz":"bunzip ", "tar.gz":"tar xfvz ", 
          "bz2":"bunzip2 ", "zip":"unzip ", "rar":"unrar ",
          "tar.bz2":"tar xfvj "}


def extract(x,y):
    # x = Dateiendung 
    # y = Pfad zur Datei
    #(von main() übergeben worden)

    try:
        befehl[x]
    except KeyError:
        print "Es wurde kein kompatibles Archiv erkannt :-(\n"
        sys.exit(0)
        
    print x + " Archiv wurde erkannt..."
    endbefehl = befehl[x] + y
    
    os.system(endbefehl)


def main():
    
    parser = OptionParser(usage="%prog [Options]", version="%prog 1.0")
      
  
    parser.add_option("-f", "--file", dest="filename",
                      help="Pfad zum Archiv FILENAME")
    
    (options, args) = parser.parse_args()

    #Beispiel für args: ['/home/benny/.gnome/gnome-vfs/.trash_entry.test']
    
    #args wird zusammengefügt.
    pfad = " ".join(args)

    #hier wird der Dateiname vom Pfad abgesplitet
    list = os.path.basename(pfad).rsplit('.', 2)
    
    #Hier wird von der Datei der Name entfern, sodass nur noch 
    #die Endung übrig bleibt:
    #z.B.  ["foo", "tar", "gz"] wird zu  ["tar", "gz"]
    list.pop(0)
    
    #Hier wird die Endung wieder zusammgegefügt. 
    #z.B: ["tar", "gz"]-->tar.gz
    extension = ".".join(list)
    
    #Ruft die extract() mit der extension als Argument auf
    extract(extension,pfad)
    
    
if __name__ == '__main__':
    main()
EnTeQuAk
User
Beiträge: 986
Registriert: Freitag 21. Juli 2006, 15:03
Wohnort: Berlin
Kontaktdaten:

Anstatt die Argumente von `extract` x und y zu nennen, kannst du sie ruhig `extension` und `path` oder so ähnlich nennen. Da sparst du gleich drei Zeilen Dokumentationscode ;)

Code: Alles auswählen

    try:
        befehl[x]
    except KeyError:
        print "Es wurde kein kompatibles Archiv erkannt :-(\n"
        sys.exit(0)
könnte man auch so machen:

Code: Alles auswählen

if not befehl.has_key(x):
    print "Es wurde kein kompatibles Archiv erkannt :-(\n"
    sys.exit(0)
sieht ein wenig schicker aus ;)

Code: Alles auswählen

    os.system(endbefehl)
[wiki=Neue_Features#Subprocess]Bitte mal anschauen ;)[/wiki]

`list` ist ein nicht gut gewählter Name. Damit überschreibst du die `__builtin__` funktion `list()`.

MfG EnTeQuAk
mitsuhiko
User
Beiträge: 1790
Registriert: Donnerstag 28. Oktober 2004, 16:33
Wohnort: Graz, Steiermark - Österreich
Kontaktdaten:

Ich sag nur unp
TUFKAB – the user formerly known as blackbird
EyDu
User
Beiträge: 4881
Registriert: Donnerstag 20. Juli 2006, 23:06
Wohnort: Berlin

EnTeQuAk hat geschrieben:könnte man auch so machen:

Code: Alles auswählen

if not befehl.has_key(x):
    print "Es wurde kein kompatibles Archiv erkannt :-(\n"
    sys.exit(0)
Ja, aber das wäre völlig "unpythonic". Aber ich muss ja zumindest noch einen Gegenvorschlag liefern:

Code: Alles auswählen

    try:
        endbefehl = befehl[x] + y
        print x + " Archiv wurde erkannt..."
        os.system(endbefehl)
    except KeyError:
        print "Es wurde kein kompatibles Archiv erkannt\n"
        sys.exit(0)
EnTeQuAk
User
Beiträge: 986
Registriert: Freitag 21. Juli 2006, 15:03
Wohnort: Berlin
Kontaktdaten:

EyDu hat geschrieben:
EnTeQuAk hat geschrieben:könnte man auch so machen:

Code: Alles auswählen

if not befehl.has_key(x):
    print "Es wurde kein kompatibles Archiv erkannt :-(\n"
    sys.exit(0)
Ja, aber das wäre völlig "unpythonic". Aber ich muss ja zumindest noch einen Gegenvorschlag liefern:

Code: Alles auswählen

    try:
        endbefehl = befehl[x] + y
        print x + " Archiv wurde erkannt..."
        os.system(endbefehl)
    except KeyError:
        print "Es wurde kein kompatibles Archiv erkannt\n"
        sys.exit(0)
Ob Pythonlike oda nicht, mag ich noch nicht zu unterscheiden... ;)

Ich sag nur unp
Immer diese Mismacher... *g*

MfG EnTeQuAk
EyDu
User
Beiträge: 4881
Registriert: Donnerstag 20. Juli 2006, 23:06
Wohnort: Berlin

EnTeQuAk hat geschrieben:Ob Pythonlike oda nicht, mag ich noch nicht zu unterscheiden... ;)
Das ist doch die gute alte EAFP-Regel (It is easier to ask for forgiveness than for permission)
bennym
User
Beiträge: 36
Registriert: Freitag 13. Oktober 2006, 21:17
Kontaktdaten:

Danke für eure Tipps+Ratschläge!

Ich habe jetzt noch einen kleinen Fehler gefixt.

Mit meiner ersten Version können Archive wie z.B. foo.txt.gz nicht entpackt werden, weil txt.gz nicht im befehl dict ist. Das geht jetzt, weil wenn .txt.gz nicht im dict ist, wird jetzt das txt weggepopt().

Sieht jetzt zwar etwas komlizierter aus, aber es funktioniert :D

mfg benny

Code: Alles auswählen

#!/usr/bin/python
# -*-coding=utf-8 -*-

from optparse import OptionParser
import os, sys

#Endung:Enpackbefehl+Leerzeichen
befehl = {"tar":"tar xfv ", "gz":"gunzip ", "tar.gz":"tar xfvz ", 
          "bz2":"bunzip2 ", "zip":"unzip ", "rar":"unrar ",
          "tar.bz2":"tar xfvj "}


def extract(extension,path,split):
    # x = Dateiendung 
    # y = Pfad zur Datei
    #(von main() übergeben worden)
    
    #print extension
    #print split
    
    try:
        #Es wird überprüft ob die extension in befehl ist.
        befehl[extension]
    except KeyError:
        #extension ist nicht vorhanden, nochmal ein Glied wird
        #abgetrennt. Z.B. erkennt die erste Routine pdf.gz nicht.
        split.pop(0)
        extension = ".".join(split)
        try:
            befehl[extension]
        except KeyError:  
            print "Es wurde kein kompatibles Archiv erkannt :-(\n"
            sys.exit(0)
        
    print extension + " Archiv wurde erkannt..."
    
    endbefehl = befehl[extension] + path
    
    if os.system(endbefehl) == 0:
        print "\n!!!Datei wurde erfolgreich entpackt!!!\n"
    else:
        print "\n!!!Entpacken fehlgeschlagen!!!\n"
        print "Ist " + befehl[extension] + "installiert?\n"


def main():
    
    parser = OptionParser(usage="%prog [Options]", version="%prog 1.0")
      
  
    parser.add_option("-f", "--file", dest="filename",
                      help="Pfad zum Archiv FILENAME")
    
    (options, args) = parser.parse_args()

    #Beispiel f+r args: ['/home/benny/.gnome/gnome-vfs/.trash_entry.test']
    
    
    #args wird zusammengefügt.
    pfad = " ".join(args)

    #hier wird der Dateiname vom Pfad abgesplitet
    split = os.path.basename(pfad).rsplit('.', 2)
    
    #Hier wird von der Datei der Name entfernt, sodass nur noch 
    #die Endung übrig bleibt:
    #z.B.  ["foo", "tar", "gz"] wird zu  ["tar", "gz"]
    split.pop(0)
    
    #print split
    
    #Hier wird die Endung wieder zusammgegefügt. 
    #z.B: ["tar", "gz"]-->tar.gz
    extension = ".".join(split)
    
    #Ruft die extract() mit der extension, dem Pfad und split auf

    extract(extension,pfad,split)
    
    
if __name__ == '__main__':
    main()
CM
User
Beiträge: 2464
Registriert: Sonntag 29. August 2004, 19:47
Kontaktdaten:

Ohne mir das wirklich näher angeschaut zu haben: Warum eigentlich

Code: Alles auswählen

sys.exit(0)
? Wo doch eigentlich angezeigt werden soll, daß das Skript nicht erfolgreich abgeschlossen wurde? Der Returncode müßte eigentlich ungleich null sein.
Dasselbe läßt sich auch so erreichen:

Code: Alles auswählen

except KeyError, msg:
    raise KeyError(msg)
, wobei msg die Fehlermeldung ist, die man vor dem "raise" natürlich auch überschreiben kann.

Allerdings kann ich verstehen, daß man darauf verzichtet, wenn man sein Skript kompatibel zu irgendwelchen uralt C-Programmen halten möchte.

Gruß,
Christian
Benutzeravatar
jens
Python-Forum Veteran
Beiträge: 8502
Registriert: Dienstag 10. August 2004, 09:40
Wohnort: duisburg
Kontaktdaten:

Irgendwie ist die ganze splitte-endung nicht optimal gelöst... Warum nicht os.path.splitext() nutzten?

Code: Alles auswählen

import os

fn = "foo.txt.gz"
print os.path.splitext(fn)
Ausgabe:
('foo.txt', '.gz')
EDIT: Ach ich sehe gerade... Es gibt ja auch ".tar.gz"... Das würde dann wieder nicht gehen... Dumm.

Und wenn ich das richtig sehe, muß man das Skript dann so nutzten:

Code: Alles auswählen

unpack.py -f /foo/bar.gz
Warum überhaupt "-f" nutzten??? Wenn es doch eh nur ein Argument gibt, kann man es IMHO weglassen... Also so:

Code: Alles auswählen

unpack.py /foo/bar.gz
Und im Skript einfach mit sys.argv[1] das nutzten. Man kann ja noch os.path.isfile() machen um zu sehen, ob die Datei auch existiert...

GitHub | Open HUB | Xing | Linked in
Bitcoins to: 1JEgSQepxGjdprNedC9tXQWLpS424AL8cd
Benutzeravatar
jens
Python-Forum Veteran
Beiträge: 8502
Registriert: Dienstag 10. August 2004, 09:40
Wohnort: duisburg
Kontaktdaten:

OK, wie wäre es damit:

Code: Alles auswählen

COMMANDS = {"tar":"tar xfv ", "gz":"gunzip ", "tar.gz":"tar xfvz ",
          "bz2":"bunzip2 ", "zip":"unzip ", "rar":"unrar ",
          "tar.bz2":"tar xfvj "}


def get_command(filename):
    ext = filename.rsplit(".", 2)[1:]
    ext = ".".join(ext)

    if ext in COMMANDS:
        return COMMANDS[ext]

    # Sonderfall wie z.B.: "foo.tar.gz"
    try:
        ext = ext.split(".")[1]
        return COMMANDS[ext]
    except IndexError, KeyError:
        raise UnknwonExtension

class UnknwonExtension(Exception):
    """
    Dateiendung ist unbekannt
    """
    pass


# Test

filenames = (
    "foo.rar", "foo.txt.gz", "foo.tar.gz", "foo.tar.bz2",
    "gibtsnicht", "foo.gibtsnicht"
)
for filename in filenames:
    print "%15s:" % filename,
    try:
        cmd = get_command(filename)
    except UnknwonExtension:
        print "Fehler!"
    else:
        print cmd
Ausgabe:

Code: Alles auswählen

        foo.rar: unrar 
     foo.txt.gz: gunzip 
     foo.tar.gz: tar xfvz 
    foo.tar.bz2: tar xfvj 
     gibtsnicht: Fehler!
 foo.gibtsnicht: Fehler!

GitHub | Open HUB | Xing | Linked in
Bitcoins to: 1JEgSQepxGjdprNedC9tXQWLpS424AL8cd
Antworten