Source code for monty.shutil

from __future__ import absolute_import
import os
import shutil
import warnings
from gzip import GzipFile

__author__ = 'Shyue Ping Ong'
__copyright__ = "Copyright 2014, The Materials Virtual Lab"
__version__ = '0.1'
__maintainer__ = 'Shyue Ping Ong'
__email__ = 'ongsp@ucsd.edu'
__date__ = '1/24/14'


[docs]def copy_r(src, dst): """ Implements a recursive copy function similar to Unix's "cp -r" command. Surprisingly, python does not have a real equivalent. shutil.copytree only works if the destination directory is not present. Args: src (str): Source folder to copy. dst (str): Destination folder. """ abssrc = os.path.abspath(src) absdst = os.path.abspath(dst) try: os.makedirs(absdst) except OSError: # If absdst exists, an OSError is raised. We ignore this error. pass for f in os.listdir(abssrc): fpath = os.path.join(abssrc, f) if os.path.isfile(fpath): shutil.copy(fpath, absdst) elif not absdst.startswith(fpath): copy_r(fpath, os.path.join(absdst, f)) else: warnings.warn("Cannot copy %s to itself" % fpath)
[docs]def gzip_dir(path, compresslevel=6): """ Gzips all files in a directory. Note that this is different from shutil.make_archive, which creates a tar archive. The aim of this method is to create gzipped files that can still be read using common Unix-style commands like zless or zcat. Args: path (str): Path to directory. compresslevel (int): Level of compression, 1-9. 9 is default for GzipFile, 6 is default for gzip. """ for f in os.listdir(path): full_f = os.path.join(path, f) if not f.lower().endswith("gz"): with open(full_f, 'rb') as f_in, \ GzipFile('{}.gz'.format(full_f), 'wb', compresslevel=compresslevel) as f_out: shutil.copyfileobj(f_in, f_out) shutil.copystat(full_f,'{}.gz'.format(full_f)) os.remove(full_f)
[docs]def compress_file(filepath, compression="gz"): """ Compresses a file with the correct extension. Functions like standard Unix command line gzip and bzip2 in the sense that the original uncompressed files are not retained. Args: filepath (str): Path to file. compression (str): A compression mode. Valid options are "gz" or "bz2". Defaults to "gz". """ if compression not in ["gz", "bz2"]: raise ValueError("Supported compression formats are 'gz' and 'bz2'.") from monty.io import zopen if not filepath.lower().endswith(".%s" % compression): with open(filepath, 'rb') as f_in, \ zopen('%s.%s' % (filepath, compression), 'wb') as f_out: f_out.writelines(f_in) os.remove(filepath)
[docs]def compress_dir(path, compression="gz"): """ Recursively compresses all files in a directory. Note that this compresses all files singly, i.e., it does not create a tar archive. For that, just use Python tarfile class. Args: path (str): Path to parent directory. compression (str): A compression mode. Valid options are "gz" or "bz2". Defaults to gz. """ for parent, subdirs, files in os.walk(path): for f in files: compress_file(os.path.join(parent, f), compression=compression)
[docs]def decompress_file(filepath): """ Decompresses a file with the correct extension. Automatically detects gz, bz2 or z extension. Args: filepath (str): Path to file. compression (str): A compression mode. Valid options are "gz" or "bz2". Defaults to "gz". """ toks = filepath.split(".") file_ext = toks[-1].upper() from monty.io import zopen if file_ext in ["BZ2", "GZ", "Z"]: with open(".".join(toks[0:-1]), 'wb') as f_out, \ zopen(filepath, 'rb') as f_in: f_out.writelines(f_in) os.remove(filepath)
[docs]def decompress_dir(path): """ Recursively decompresses all files in a directory. Args: path (str): Path to parent directory. """ for parent, subdirs, files in os.walk(path): for f in files: decompress_file(os.path.join(parent, f))