1

When I first coded this in to a single function, it worked. But I want to do more things when I am checking for files in to the directory, so I have divided the code in two functions : One checks for files on a directory that end with *.rar extension, if it finds a file that matches, it uncompresses it to a directory.

import shutil, os, patoolib, fnmatch, glob


def unrar():

        patoolib.extract_archive(file, outdir="/root/tree/def")



def chktree():

        for file in glob.glob('/root/tree/down/*'):
                if fnmatch.fnmatch(file, '*.rar'):
                        unrar()

chktree()

Executing unrar() after the if from the function chktree(): does not work. I would like to know what I am doing wrong, this is the output :

Traceback (most recent call last):
  File "autotube.py", line 16, in <module>
    chktree()
  File "autotube.py", line 14, in chktree
    unrar()
  File "autotube.py", line 6, in unrar
    patoolib.extract_archive(file, outdir="/root/tree/def")
  File "/usr/local/lib/python2.7/dist-packages/patoolib/__init__.py", line 676, in extract_archive
    util.check_existing_filename(archive)
  File "/usr/local/lib/python2.7/dist-packages/patoolib/util.py", line 389, in check_existing_filename
    if not os.path.exists(filename):
  File "/usr/lib/python2.7/genericpath.py", line 26, in exists
    os.stat(path)
TypeError: coercing to Unicode: need string or buffer, type found
ivan_pozdeev
  • 33,874
  • 19
  • 107
  • 152
xavier
  • 746
  • 2
  • 12
  • 22
  • Is there any reason you're not just doing `glob.glob('/root/tree/down/*.rar')`? – mgilson Jan 11 '16 at 07:51
  • Dont set `file` as variable name , it's built_in name in Python – ᴀʀᴍᴀɴ Jan 11 '16 at 07:53
  • Possible duplicate of [Is it bad practice to use a built-in function name as an attribute or method identifier?](http://stackoverflow.com/questions/9109333/is-it-bad-practice-to-use-a-built-in-function-name-as-an-attribute-or-method-ide) – ivan_pozdeev Jan 11 '16 at 08:02
  • After looking closely, looks more like "trivial or syntax error": using an undeclared name that just happened to be declared elsewhere. Failed to add so much as a debug printing, too. – ivan_pozdeev Jan 11 '16 at 08:07

2 Answers2

3

You need to pass the variable file explicitly to the function you are calling. Also, file is a special name in Python, so you should probably use a different name, such as my_file or simply f.

import shutil, os, patoolib, fnmatch, glob

def unrar(my_file):
        patoolib.extract_archive(my_file, outdir="/root/tree/def")

def chktree():
        for f in glob.glob('/root/tree/down/*'):
                if fnmatch.fnmatch(f, '*.rar'):
                        unrar(f)
chktree()

Additionally, as @mgilson noted, the reason for the actual error you are seeing is that Python thinks you are referring to the built-in name file since you did not pass a parameter which shadowed it. Had you used a different name, you would have gotten a NameError instead.

merlin2011
  • 71,677
  • 44
  • 195
  • 329
  • 1
    I think that this is the likely candidate -- However, with OP's code, I don't think a `TypeError` would have been raised. He would have gotten a `NameError` if this was the case and the code posted above (in the question) is correct (which it likely isn't). – mgilson Jan 11 '16 at 07:53
  • Also, can I recommend using PEP-8 names -- e.g. `my_file` rather than `myFile` :-) – mgilson Jan 11 '16 at 07:54
  • 1
    @mgilson, I think it was a combination of reusing a built-in name and the lack of parameters. – merlin2011 Jan 11 '16 at 07:54
  • Oh, shoot.. Python2.x -- right, `file` is a builtin. That explains it. – mgilson Jan 11 '16 at 07:55
  • @mgilson, Sure, I can change those names. – merlin2011 Jan 11 '16 at 07:55
3

In python 2, there is a file builtin, which is what you are calling extract_archive with in your unrar function. You are not using your loop variable from chktree because it only lives within chktree. You can write it like this:

def unrar(f):
    patoolib.extract_archive(f, outdir="/root/tree/def")

def chktree():    
    for f in glob.glob('/root/tree/down/*'):
        if fnmatch.fnmatch(f, '*.rar'):
            unrar(f)

I used f as the name for the file to prevent masking the builtin.

timgeb
  • 76,762
  • 20
  • 123
  • 145
  • Ok, that worked. I used the built_in because I was consulting the python docs when I did it, and they use the built_in as an example. Thank you. – xavier Jan 11 '16 at 08:06
  • @xavier maybe you read the Python3 docs? `file` is not a builtin there. – timgeb Jan 11 '16 at 08:09
  • I just checked, those are the docs for Python 2.7.11 : https://docs.python.org/2/library/fnmatch.html – xavier Jan 11 '16 at 08:11
  • 1
    @xavier yup, they are masking the builtin in that loop. It does not make a difference in their example, but still not a good practice. – timgeb Jan 11 '16 at 08:13