Python: how could I access tarfile.add()'s 'name' parameter in add()'s filter method?
<p>I would like to filter subdirectories (skip them) while creating tar(gz) file with <strong>tarfile</strong> (python 3.4).</p>

<p>Files on disk:</p>

<ul>
<li>/home/myuser/temp/test1/</li>
<li>/home/myuser/temp/test1/home/foo.txt</li>
<li>/home/myuser/temp/test1/thing/bar.jpg</li>
<li>/home/myuser/temp/test1/lemon/juice.png</li>
<li>/home/myuser/temp/test1/</li>
</ul>

<p>Tried to compress <code>/home/myuser/temp/test1/</code> by <code>tarfile.add()</code>.</p>

<p>I use with- and without-path modes. With full path it's OK, but with short path I have this problem:
<strong>directory exclusion doesn't work because tarfile.add() passes the <em><code>arcname</code></em> parameter to filter method - not <code>name</code> parameter!</strong></p>

<blockquote>
  <p>archive.add(entry, arcname=os.path.basename(entry),
  filter=self.filter_general)</p>
</blockquote>

<p>Example:</p>

<p>file: <code>/home/myuser/temp/test1/thing/bar.jpg</code>   -> <code>arcname = test1/thing/bar.jpg</code></p>

<p>So because of <code>/home/myuser/temp/test1/thing</code> element in <code>exclude_dir_fullpath</code>, the filter method should exclude this file, but it can not because filter method gets <code>test1/thing/bar.jpg</code>.</p>

<p><strong>How could I access tarfile.add()'s 'name' parameter in filter method?</strong></p>

<pre><code>def filter_general(item):
    exclude_dir_fullpath = ['/home/myuser/temp/test1/thing', '/home/myuser/temp/test1/lemon']
    if any(dirname in item.name for dirname in exclude_dir_fullpath):
        print("Exclude fullpath dir matched at: %s" % item.name)  # DEBUG
        return None
    return item


def compress_tar():
    filepath = '/tmp/test.tar.gz'
    include_dir = '/home/myuser/temp/test1/'
    archive = tarfile.open(name=filepath, mode="w:gz")
    archive.add(include_dir, arcname=os.path.basename(include_dir), filter=filter_general)

compress_tar()
</code></pre>

<p>You want to create a general/re-useable function to filter out files given their absolute path name. I understand that filtering on the archive name is not enough since sometimes it would be OK to include a file or not depending on where it is originated.</p>

<p>First, add a parameter to your filter function</p>

<pre><code>def filter_general(item,root_dir):
    full_path = os.path.join(root_dir,item.name)
</code></pre>

<p>Then, replace your "add to archive" code line by:</p>

<pre><code>archive.add(include_dir, arcname=os.path.basename(include_dir), filter=lambda x: filter_general(x,os.path.dirname(include_dir)))
</code></pre>

<p>the filter function has been replaced by a <code>lambda</code> which passes the directory name of the include directory (else, root dir would be repeated)</p>

<p>Now your filter function knows the root dir and you can filter by absolute path, allowing you to reuse your filter function in several locations in your code.</p>

python filter compression tarfile