10

I want to compress one text file using shutil.make_archive command. I am using the following command:

shutil.make_archive('gzipped'+fname, 'gztar', os.path.join(os.getcwd(), fname))

OSError: [Errno 20] Not a directory: '/home/user/file.txt'

I tried several variants but it keeps trying to compress the whole folders. How to do it correctly?

minerals
  • 6,090
  • 17
  • 62
  • 107

6 Answers6

21

Actually shutil.make_archive can make one-file archive! Just pass path to target directory as root_dir and target filename as base_dir.

Try this:

import shutil

file_to_zip = 'test.txt'            # file to zip
target_path = 'C:\\test_yard\\'     # dir, where file is

try:
    shutil.make_archive(target_path + 'archive', 'zip', target_path, file_to_zip)
except OSError:
    pass
CommonSense
  • 4,232
  • 2
  • 14
  • 38
  • What's the minimum version for this to work? At python 2.7.6 supplying a filename as base_dir resulted in an empty zip files – Oliver Zendel Oct 12 '18 at 09:21
5

shutil can't create an archive from one file. You can use tarfile, instead:

tar = tarfile.open(fname + ".tar.gz", 'w:qz')
os.chdir('/home/user')
tar.add("file.txt")
tar.close()

or

tar = tarfile.open(fname + ".tar.gz", 'w:qz')
tar.addfile(tarfile.TarInfo("/home/user/file.txt"), "/home/user/file.txt")
tar.close()
pedromanoel
  • 3,232
  • 2
  • 24
  • 23
Kirikami
  • 321
  • 4
  • 11
3

Try this and Check shutil

copy your file to a directory.

cd directory

shutil.make_archive('gzipped', 'gztar', os.getcwd())
Ajay
  • 5,267
  • 2
  • 23
  • 30
1

@CommonSense had a good answer, but the file will always be created zipped inside its parent directories. If you need to create a zipfile without the extra directories, just use the zipfile module directly

import os, zipfile
inpath  = "test.txt"
outpath = "test.zip"
with zipfile.ZipFile(outpath, "w", compression=zipfile.ZIP_DEFLATED) as zf:
    zf.write(inpath, os.path.basename(inpath))
user2682863
  • 3,097
  • 1
  • 24
  • 38
0

If you don't mind doing a file copy op:

def single_file_to_archive(full_path, archive_name_no_ext):
    tmp_dir = tempfile.mkdtemp()
    shutil.copy2(full_path, tmp_dir)
    shutil.make_archive(archive_name_no_ext, "zip", tmp_dir, '.')
    shutil.rmtree(tmp_dir)
Oliver Zendel
  • 2,695
  • 34
  • 29
0

Archiving a directory to another destination was a pickle for me but shutil.make_archive not zipping to correct destination helped a lot.

from shutil import make_archive
make_archive(
    base_name=path_to_directory_to_archive},
    format="gztar",
    root_dir=destination_path,
    base_dir=destination_path)
Ferris
  • 51
  • 2