A compressed file can be classified into below logical groups
a. The operating system which you are working on (*ix, Win) etc.
b. Different types of compression algorithm (i.e .zip,.Z,.bz2,.rar,.gzip). Atleast from a standard list of mostly used compressed files.
c. Then we have tar ball mechanism - where I suppose there are no compression. But it acts more like a concatenation.
Now, if we start addressing the above set of compressed files,
a. Option (a) would be taken care by python since it is platform independent language.
b. Option (b) and (c) seems to have a problem.
What do I need
How do I identify the file type (compression type) and then UN-compress them?
Like:
fileType = getFileType(fileName)
switch(fileType):
case .rar: unrar....
case .zip: unzip....
etc
So the fundamental question is how do we identify the compression algorithm based on the file (assuming the extension is not provided or incorrect)? Is there any specific way to do it in python?
This is a complex question that depends on a number of factors: the most important being how portable your solution needs to be.
The basics behind finding the file type given a file is to find an identifying header in the file, usually something called a "magic sequence" or signature header, which identifies that a file is of a certain type. Its name or extension is usually not used if it can be avoided. For some files, Python has this built in. For example, to deal with
.tar
files, you can use thetarfile
module, which has a convenientis_tarfile
method. There is a similar module namedzipfile
. These modules will also let you extract files in pure Python.For example:
If your solution is Linux or OSX only, there is also the
file
command which will do a lot of the work for you. You can also use the built-in tools to uncompress the files. If you are just doing a simple script, this method is simpler and will give you better performance.This page has a list of "magic" file signatures. Grab the ones you need and put them in a dict like below. Then we need a function that matches the dict keys with the start of the file. I've written a suggestion, though it can be optimized by preprocessing the
magic_dict
into e.g. one giant compiled regexp.This solution should be cross-plattform and is of course not dependent on file name extension, but it may give false positives for files with random content that just happen to start with some specific magic bytes.
If the exercise is to identify it just to label files, you have lots of answers. If you want to uncompress the archive, why don't you just try and catch the execptions/errors? For example:
"a" is completely false.
"b" can be easily interpreted badly, as ".zip" doesn't mean the file is actually a zip file. It could be a JPEG with zip extension (for confusing purposes, if you want).
You actually need to check if the data inside the file matches the data expected to have by it's extension. Also have a look at magic byte.
Based on lazyr's answer and my comment, here is what I mean:
Can now access the compressed data using
cf.accessor
. All the modules provide similar methods like 'read()', 'write()', etc. to do this.