您已声明需要支持“tar、bz2、zip 或 tar.gz”。 Python 的 tarfile 模块会自动处理 gz 和 bz2 压缩的 tar 文件,因此您实际上只需要支持 2 种类型的存档:tar 和 zip。 (bz2 本身不是存档格式,它只是压缩)。
您可以使用tarfile.is_tarfile() 确定给定文件是否为tar 文件。这也适用于使用 gzip 或 bzip2 压缩的 tar 文件。在 tar 文件中,您可以确定文件是使用 TarInfo.isdir() 的目录还是使用 TarInfo.isfile() 的文件。
同样,您可以使用zipfile.is_zipfile() 确定文件是否为 zip 文件。 zipfile 没有办法区分目录和普通文件,但以/ 结尾的文件是目录。
所以,给定一个文件名,你可以这样做:
import zipfile
import tarfile
filename = 'test.tgz'
if tarfile.is_tarfile(filename):
f = tarfile.open(filename)
for info in f:
if info.isdir():
file_type = 'directory'
elif info.isfile():
file_type = 'file'
else:
file_type = 'unknown'
print('{} is a {}'.format(info.name, file_type))
elif zipfile.is_zipfile(filename):
f = zipfile.ZipFile(filename)
for name in f.namelist():
print('{} is a {}'.format(name, 'directory' if name.endswith('/') else 'file'))
else:
print('{} is not an accepted archive file'.format(filename))
在具有这种结构的 tar 文件上运行时:
(py2)[mhawke@localhost tmp]$ tar tvfz /tmp/test.tgz
drwxrwxr-x mhawke/mhawke 0 2016-02-29 12:38 x/
lrwxrwxrwx mhawke/mhawke 0 2016-02-29 12:38 x/4 -> 3
drwxrwxr-x mhawke/mhawke 0 2016-02-28 21:14 x/3/
drwxrwxr-x mhawke/mhawke 0 2016-02-28 21:14 x/3/4/
-rw-rw-r-- mhawke/mhawke 0 2016-02-28 21:14 x/3/4/zzz
drwxrwxr-x mhawke/mhawke 0 2016-02-28 21:13 x/2/
-rw-rw-r-- mhawke/mhawke 0 2016-02-28 21:13 x/2/aa
drwxrwxr-x mhawke/mhawke 0 2016-02-28 21:13 x/1/
-rw-rw-r-- mhawke/mhawke 0 2016-02-28 21:13 x/1/abc
-rw-rw-r-- mhawke/mhawke 0 2016-02-28 21:13 x/1/ab
-rw-rw-r-- mhawke/mhawke 0 2016-02-28 21:13 x/1/a
输出是:
x 是一个目录
x/4 是未知数
x/3 是一个目录
x/3/4 是一个目录
x/3/4/zzz 是一个文件
x/2 是一个目录
x/2/aa 是一个文件
x/1 是一个目录
x/1/abc 是一个文件
x/1/ab 是一个文件
x/1/a 是一个文件
注意x/4 是“未知的”,因为它是一个符号链接。
zipfile 没有简单的方法可以将符号链接(或其他文件类型)与目录或普通文件区分开来。信息在ZipInfo.external_attr 属性中,但是把它拿回来很麻烦:
import stat
linked_file = f.filelist[1]
is_symlink = stat.S_ISLNK(linked_file.external_attr >> 16L)