Script zum entpacken von Archiven unter Linux

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

Script zum entpacken von Archiven unter Linux

Beitragvon bennym » Mittwoch 2. Mai 2007, 19:52

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:

Beitragvon EnTeQuAk » Mittwoch 2. Mai 2007, 20:09

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
Benutzeravatar
mitsuhiko
User
Beiträge: 1790
Registriert: Donnerstag 28. Oktober 2004, 16:33
Wohnort: Graz, Steiermark - Österreich
Kontaktdaten:

Beitragvon mitsuhiko » Mittwoch 2. Mai 2007, 23:04

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

Beitragvon EyDu » Donnerstag 3. Mai 2007, 09:40

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:

Beitragvon EnTeQuAk » Donnerstag 3. Mai 2007, 10:32

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: 4866
Registriert: Donnerstag 20. Juli 2006, 23:06
Wohnort: Berlin

Beitragvon EyDu » Donnerstag 3. Mai 2007, 10:44

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:

Beitragvon bennym » Freitag 4. Mai 2007, 15:45

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:

Beitragvon CM » Dienstag 8. Mai 2007, 08:10

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
Moderator
Beiträge: 8458
Registriert: Dienstag 10. August 2004, 09:40
Wohnort: duisburg
Kontaktdaten:

Beitragvon jens » Dienstag 8. Mai 2007, 10:27

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=]unpack.py -f /foo/bar.gz[/code]

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

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...

CMS in Python: http://www.pylucid.org
GitHub | Open HUB | Xing | Linked in
Bitcoins to: 1JEgSQepxGjdprNedC9tXQWLpS424AL8cd
Benutzeravatar
jens
Moderator
Beiträge: 8458
Registriert: Dienstag 10. August 2004, 09:40
Wohnort: duisburg
Kontaktdaten:

Beitragvon jens » Dienstag 8. Mai 2007, 10:45

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=] foo.rar: unrar
foo.txt.gz: gunzip
foo.tar.gz: tar xfvz
foo.tar.bz2: tar xfvj
gibtsnicht: Fehler!
foo.gibtsnicht: Fehler![/code]

CMS in Python: http://www.pylucid.org
GitHub | Open HUB | Xing | Linked in
Bitcoins to: 1JEgSQepxGjdprNedC9tXQWLpS424AL8cd

Wer ist online?

Mitglieder in diesem Forum: 0 Mitglieder