Does anyone here know how to use the UnRAR2 module?
http://code.google.com/p/py-unrar2/downloads/list

I can't for the life of me I can't figure out how get it to do the same thing that zipfile does in a project I am working on. I want it to look for all files of a specific file type, print their name, and extract them to a specific directory. And do this for 4 different file types.

Here is the working code using zipfile:

def unzip():

    try:
        os.chdir(fileDir)

        zip = zipfile.ZipFile(filename, "r")
        print "\n---------------------------"
        print "Installing..."
        
        for name in zip.namelist():
            
            if name.find(".package") != -1:
                print "Found %s. Extracting to \Packages." % name
                zip.extract(name, modDir + "\Packages")

            elif name.find(".dbc") != -1:
                print "Found %s. Extracting to \DCCache." % name
                zip.extract(name, modDir + "\DCCache")
            else:
                print "No valid files found."

Now here is the test code I came up with when reading the module docs. I didn't really understand it.

def unrar():
    
    try:
        os.chdir(fileDir)

        archive = UnRAR2.RarFile(filename)
        print "\n---------------------------"
        print "Installing..."

        for fileInArchive in archive.infoiter():
            os.path.split(fileInArchive.filename)[1]

            if fileInArchive.filename == "*.txt":
                print "That is a text file."

Of course, it doesn't work. Does anyone know how to make UnRAR2 do this? Or is there something better to use when working with .rar files?

Recommended Answers

All 22 Replies

test_UnRAR2.py

If you take a look at this, it will get easier.

I can tested but i think something likethis maybe. :)

for rarinfo in archive.infoiter():
    if rarinfo.filename == "*.txt":
        # your code

Check the documentation on os.path.split . I think it returns a tuple (name, extension) .

for fileInArchive in archive.infoiter():
    extension = os.path.split(fileInArchive.filename)[1]
    if extension == "txt":
        print "This is a text file"

Thanks for both replies. Both of the codes seem to do their job...Here is the code I have now. I tried to make it handle just like my program handles .zip files since now I know how to get the file name. It sort of works...

def unrar():

    try:
        os.chdir(fileDir)
        
        archive = UnRAR2.RarFile(filename)
        print "\n-------------"
        print "Installing..."
        print "-------------\n"

        for rarinfo in archive.infoiter():
            name = rarinfo.filename
            
            if name.find(".package") != -1:
                print "Found %s. Extracting to \Packages." % name
                archive.extract(name, modDir + "\Packages")

            elif name.find(".dbc") != -1:
                print "Found %s. Extracting to \DCCache." % name
                archive.extract(name, modDir + "\DCCache")

            else:
                print "No valid files found."
                os.system("pause")
                os.system("cls")
                checkExtension()

        print "\nInstallation successful!"
        os.system("pause")

Result using my test archive. It has two files, Package.package and dbda.dbc, so it should print that it has found both files to the console and extract them to the appropriate location.

Drag and drop the file into this window and press enter.
C:\123.rar

-------------
Installing...
-------------

Found Package.package. Extracting to \Packages.

Installation successful!
>>>

Why is it skipping the check for a .dbc file? I even added another check for a text file and it still only detected the .package. And it's not even extracting the .package file even though it was found.

What escape codes are \P and \D, they are new to me?

Maybe they are unknown, and pass through, but safe way is to for example say:

archive.extract(name, modDir + r"\DCCache")

It is skipping the check for the .dbc file because it found a .package file. In the if..elif..else statement only one block will be executed. When the if condition is found to be true, the elif and else are skipped. Change your code to use only if statements.

def unrar():
    try:
        os.chdir(fileDir)
        
        archive = UnRAR2.RarFile(filename)
        print "\n-------------"
        print "Installing..."
        print "-------------\n"

        for rarinfo in archive.infoiter():
            name = rarinfo.filename
            found = False
            
            if name.find(".package") != -1:
                print "Found %s. Extracting to \Packages." % name
                archive.extract(name, modDir + "\Packages")
                found = True

            #elif name.find(".dbc") != -1:
            if name.find(".dbc") != -1:
                print "Found %s. Extracting to \DCCache." % name
                archive.extract(name, modDir + "\DCCache")
                found = True

            #else:
            if not found:
                print "No valid files found."
                os.system("pause")
                os.system("cls")
                checkExtension()

        print "\nInstallation successful!"
        os.system("pause")

Tony I believe they are path directories names, but if it is so they should be doubled.

Something like this:

if name.find(".package") != -1:
                print "Found %s. Extracting to \\Packages." % name
                archive.extract(name, modDir + "\\Packages")
                found = True

Tony I believe they are path directories names, but if it is so they should be doubled.

Yes, they are path names. Strange, though. They've been working the way I've had them since I started working on this. :-O
Oh well, I changed them anyway.

Change your code to use only if statements.

This is strange, too. My code to unzip a file at the top used if elif and else and it works just fine. Anyways I tried that and it still only finds the .package file and still does not extract it.

Just a thought...

for rarinfo in archive.infoiter():
            name = rarinfo.filename # <--------- Here
            found = False
            
            if name.find(".package") != -1:
                print "Found %s. Extracting to \Packages." % name
                archive.extract(name, modDir + "\\Packages")
                found = True

            if name.find(".dbc") != -1:
                print "Found %s. Extracting to \DCCache." % name
                archive.extract(name, modDir + "\\DCCache")
                found = True

            if not found:
                print "No valid files found."
                os.system("pause")
                os.system("cls")
                checkExtension()

Could the program be finding Package.package first (it is the first file in the archive) and then keep checking for it instead of looking for the next file extension? I think that's what I'm trying to say. :?:

What's the OS you are coding on?

And how about this.

if name.find(".package") != -1:
                print "Found %s. Extracting to \\Packages." % name
                archive.extract(name, modDir + "\\Packages", False)
                found = True

Edit:

class RarInfo(__builtin__.object)
Represents a file header in an archive. Don't instantiate directly.
Use only to obtain information about file.
YOU CANNOT EXTRACT FILE CONTENTS USING THIS OBJECT.
USE METHODS OF RarFile CLASS INSTEAD.

So....

class RarFile

__del__(self)

__init__(self, archiveName, password=None)
    Instantiate the archive.
     
    archiveName is the name of the RAR file.
    password is used to decrypt the files in the archive.
     
    Properties:
        comment - comment associated with the archive
     
    >>> print RarFile('test.rar').comment
    This is a test.

extract(self, condition='*', path='.', withSubpath=True)
    Extract specific files from archive to disk.
     
    If "condition" is a list of numbers, then extract files which have those positions in infolist.
    If "condition" is a string, then it is treated as a wildcard for names of files to extract.
    If "condition" is a function, it is treated as a callback function, which accepts a RarInfo object
        and returns either boolean True (extract) or boolean False (skip).
    DEPRECATED: If "condition" callback returns string (only supported for Windows) - 
        that string will be used as a new name to save the file under.
    If "condition" is omitted, all files are extracted.
     
    "path" is a directory to extract to
    "withSubpath" flag denotes whether files are extracted with their full path in the archive.
     
    Returns list of RarInfos for extracted files.

infoiter(self)
    Iterate over all the files in the archive, generating RarInfos.
     
    >>> import os
    >>> for fileInArchive in RarFile('test.rar').infoiter():
    ...     print os.path.split(fileInArchive.filename)[-1],
    ...     print fileInArchive.isdir,
    ...     print fileInArchive.size,
    ...     print fileInArchive.comment,
    ...     print tuple(fileInArchive.datetime)[0:5],
    ...     print time.strftime('%a, %d %b %Y %H:%M', fileInArchive.datetime)
    test True 0 None (2003, 6, 30, 1, 59) Mon, 30 Jun 2003 01:59
    test.txt False 20 None (2003, 6, 30, 2, 1) Mon, 30 Jun 2003 02:01
    this.py False 1030 None (2002, 2, 8, 16, 47) Fri, 08 Feb 2002 16:47

infolist(self)
    Return a list of RarInfos, descripting the contents of the archive.

read_files(self, condition='*')
    Read specific files from archive into memory.
    If "condition" is a list of numbers, then return files which have those positions in infolist.
    If "condition" is a string, then it is treated as a wildcard for names of files to extract.
    If "condition" is a function, it is treated as a callback function, which accepts a RarInfo object 
        and returns boolean True (extract) or False (skip).
    If "condition" is omitted, all files are returned.
     
    Returns list of tuples (RarInfo info, str contents)

I'm on Windows XP.

Ok I'm looking through that...I think I can do this now.

def unrar():

    try:
        os.chdir(fileDir)
        
        print "\n-------------"
        print "Installing..."
        print "-------------\n"

        found = None
		
        for filename in Unrar2.RarFile(filename).infoiter():
			
	    basename, ext = os.path.splitext(filename)
			
            if ext == ".package":
                print "Found %s. Extracting to \\Packages." % filename
                archive.extract(filename, modDir + "\\Packages", False)
                found == True
				
            elif ext == ".dbc":
                print "Found %s. Extracting to \\DCCache." % filename
                archive.extract(filename, modDir + "\\DCCache", False)
                found == True
				
        if found:
            print "\nInstallation successful!"
	    os.system("pause")
        else:
            print "No valid files found."
            os.system("pause")
            os.system("cls")
            checkExtension()

Alright now this just outright doesn't make sense to me...

for filename in UnRAR2.RarFile(filename).infoiter():
UnboundLocalError: local variable 'filename' referenced before assignment

:confused:

Oups... :)

I was sleeping.

def unrar():

    try:
        os.chdir(fileDir)
        
        print "\n-------------"
        print "Installing..."
        print "-------------\n"

        found = None
		
        for file in Unrar2.RarFile(filename).infoiter():
			
	    basename, ext = os.path.splitext(file)
			
            if ext == ".package":
                print "Found %s. Extracting to \\Packages." % file
                archive.extract(file, modDir + "\\Packages", False)
                found == True
				
            elif ext == ".dbc":
                print "Found %s. Extracting to \\DCCache." % file
                archive.extract(file, modDir + "\\DCCache", False)
                found == True
				
        if found:
            print "\nInstallation successful!"
	    os.system("pause")
        else:
            print "No valid files found."
            os.system("pause")
            os.system("cls")
            checkExtension()

Uh oh, another error..

basename, ext = os.path.splitext(file)
  File "C:\Python26\lib\ntpath.py", line 190, in splitext
    return genericpath._splitext(p, sep, altsep, extsep)
  File "C:\Python26\lib\genericpath.py", line 91, in _splitext
    sepIndex = p.rfind(sep)
AttributeError: 'RarInfo' object has no attribute 'rfind'

Now that REALLY doesn't make sense.

I'm sorry but I can't test it where I am now, and I'm a litle sleepy. :)

But I think now I got it.

def unrar():

    try:
        os.chdir(fileDir)
        
        print "\n-------------"
        print "Installing..."
        print "-------------\n"

        found = None
        archive = Unrar2.RarFile(filename)	
        
        for file_archive in archive.infoiter():

            file = os.path.split(file_archive.filename)[-1]			

	    basename, ext = os.path.splitext(file)
			
            if ext == ".package":
                print "Found %s. Extracting to \\Packages." % file
                archive.extract(file, modDir + "\\Packages", False)
                found == True
				
            elif ext == ".dbc":
                print "Found %s. Extracting to \\DCCache." % file
                archive.extract(file, modDir + "\\DCCache", False)
                found == True
				
        if found:
            print "\nInstallation successful!"
	    os.system("pause")
        else:
            print "No valid files found."
            os.system("pause")
            os.system("cls")
            checkExtension()

That's ok don't worry about it. This doesn't have to be finished immediately or anything.

EDIT: Didn't realize that you edited the code above.

Now it just does the same thing it's been doing.. :-\

Drag and drop the file into this window and press enter.
C:\123.rar

-------------
Installing...
-------------

Found Package.package. Extracting to \Packages.
No valid files found.

Sorry but this is my last try for today, I'm too tired.

Try like this, otherwise tomorrow I'll download the package and try it.

def unrar():

    try:
        os.chdir(fileDir)
        
        print "\n-------------"
        print "Installing..."
        print "-------------\n"

        found = None
        archive = Unrar2.RarFile(filename)	
        
        for file_archive in Unrar2.RarFile(filename).infoiter():

            file = os.path.split(file_archive.filename)[-1]			

	    basename, ext = os.path.splitext(file)
			
            if ext == ".package":
                print "Found %s. Extracting to \\Packages." % file
                archive.extract(file, modDir + "\\Packages", False)
                found == True
				
            elif ext == ".dbc":
                print "Found %s. Extracting to \\DCCache." % file
                archive.extract(file, modDir + "\\DCCache", False)
                found == True
				
        if found:
            print "\nInstallation successful!"
	    os.system("pause")
        else:
            print "No valid files found."
            os.system("pause")
            os.system("cls")
            checkExtension()

That's perfectly fine.

Finally it detects both files! It still won't extract though. I'm gonna keep messing with it, I think I can figure it out.

def unrar():

    try:
        os.chdir(fileDir)
        
        print "\n-------------"
        print "Installing..."
        print "-------------\n"

        found = None
        archive = Unrar2.RarFile(filename)	
        
        for file_archive in Unrar2.RarFile(filename).infoiter():

            file = os.path.split(file_archive.filename)[-1]			

	    basename, ext = os.path.splitext(file)
			
            if ext == ".package":
                print "Found %s. Extracting to \\Packages." % file
                archive.extract(file_archive, modDir + "\\Packages", False)
                found == True
				
            elif ext == ".dbc":
                print "Found %s. Extracting to \\DCCache." % file
                archive.extract(file_archive, modDir + "\\DCCache", False)
                found == True
				
        if found:
            print "\nInstallation successful!"
	    os.system("pause")
        else:
            print "No valid files found."
            os.system("pause")
            os.system("cls")
            checkExtension()
archive.extract(file_archive, modDir + "\\Packages", False)
  File "C:\Python26\lib\site-packages\UnRAR2\__init__.py", line 154, in extract
    checker = condition2checker(condition)
  File "C:\Python26\lib\site-packages\UnRAR2\__init__.py", line 170, in condition2checker
    raise TypeError
TypeError

SOLVED!!!

I finally got it working after reading this.

"The main limitation of the UnRAR.dll library is that it cannot be used to extract or access individual files in archive. The whole archive must always be processed in one pass."

I understand it like this: It was only extracting .package files because that was all that UnRAR.dll allowed to be processed. I added archive = UnRAR2.RarFile(filename) to the beginning of the for loop so the archive is opened again so it can look for the next file extension.

def unrar():

    try:
        os.chdir(fileDir)
        
        archive = UnRAR2.RarFile(filename)
        print "\n-------------"
        print "Installing..."
        print "-------------\n"

        for fileInArchive in UnRAR2.RarFile(filename).infoiter():
            archive = UnRAR2.RarFile(filename) 
            file = os.path.split(fileInArchive.filename)[-1]			
            basename, ext = os.path.splitext(file)

            if ext == ".package":
                print "Found %s. Extracting to \\Packages." % file
                archive.extract("*.package", modDir + "\\Packages")
                found = True

            elif ext == ".dbc":
                print "Found %s. Extracting to \\DCCache." % file
                archive.extract("*.dbc", modDir + "\\DCCache")
                found = True
                
        if found == True:
            print "\nInstallation successful!"
            os.system("pause")
            
        else:
            print "\nThere was a problem with the installation."
            os.system("pause")
            
    except WindowsError:
        print "File not found."
        os.system("pause")
        os.system("cls")
        checkExtension()

I'm sorry for the late night cerebral obstipation. :D

I see you were more waken than me, I like your final code, you can delete line 6. It's doing nothing there nomore since the for loop don't use it, and you rewrite it on the begiining of the loop.

Congrats and happy coding.

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.