add file to tar with chmod +x python

Viewed 354

I have tar.gz file like:

tmp/
tmp/picture/
tmp/picture/1.jpg

I want to add to this tar.gz file with python file to tmp/logger.sh with chmod +x

How can I do that ?

import tarfile
with tarfile.open('test.tar.gz','w') as f:
    f.add('logger.sh' , arcname='/tmp/logger.sh')

That give me tar file /tmp/logger.sh file but remove the rest of files that was in the tar file + I can't set chmod +x to this file

3 Answers

The mode may have to be set explicitly like (default is r):

tarfile.open('test.tar.gz','a')

See also tarfile.open docs.

File permission settings of a TarInfo objects can be done with TarInfo.mode.

Edit: Here the long version:

 $ python3.8
Python 3.8.0a1 (default, Feb  3 2019, 20:37:37)
[GCC 7.3.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import tarfile
>>> fh = tarfile.open('/tmp/test.tar.gz', 'w')
>>> fh.add("/home/chris/.zshrc")
>>> fh.add("/home/chris/.zcompdump")
>>> fh.list()
[...] home/chris/.zshrc
[...] home/chris/.zcompdump
>>> fh.close()
>>>
>>> fh = tarfile.open('/tmp/test.tar.gz', 'a')
>>> fh.add("/home/chris/.bashrc")
>>> fh.list()
[...] home/chris/.zshrc
[...] home/chris/.zcompdump
[...] home/chris/.bashrc
>>>

So it works fine just using a without the :gz.

The absolutely simplest solution is to (temporarily?) chmod the file before adding it.

As you already discovered, 'w' mode will overwrite any existing file. To update an existing archive, you want to open the file in 'a' mode instead.

However, unfortunately, the tarfile library does not support opening a gz file in a mode. You can do this if you have an uncompressed file:

import tarfile

def chmodx(tarinfo):
    tarinfo.mode = int('0755', base=8)
    return tarinfo

with tarfile.open('test.tar', 'a'):
    f.add('logger.sh' , arcname='/tmp/logger.sh', filter=chmodx)

The nature of gz compression is such that you probably simply want to uncompress the file, update it, and then recompress, rather than do it all in one go. Ideally, you'd want to do this in memory, but that's problematic if the uncompressed tar file is large.

I think the easiest way to do that is to directly use the tar command like this:

import os
#Ici, on a newFilePath=tmp/logger.sh

command = "tar rf {1} {2} --mode=755".format(tarFilePath,newFilePath)
os.system(command)
Related