这是一种记录在案的行为,有点奇怪。 make_archive 的 base_dir 参数记录到:
- 成为我们开始归档的目录(在
chdiring 到root_dir 之后)
- 默认为当前目录(具体来说,
os.curdir)
os.curdir 实际上是一个常量字符串'.',并且与tar 命令行实用程序匹配,shutil.make_archive(以及它的实现方式tar.add)存储完整路径“给定”(在这种情况下,'./' 加上文件的其余相对路径)。如果你运行tar -c -z -C directoryX -f NameOfArchive.tar.gz .,你最终也会得到一个包含./前缀文件的压缩包(-C directoryX与root_dir做同样的事情,.参数与默认@987654337相同@)。
我没有看到一个简单的解决方法可以保留shutil.make_archive 的简单性;如果你尝试传递 base_dir='',它会在尝试传递 stat '' 时死掉,所以就不行了。
要清楚,这种行为应该没问题;在大多数情况下,一个名为 ./foo 的 tar 条目和一个名为 foo 的 tar 条目是等效的。如果实在困扰你,你可以直接切换到使用tarfile模块,例如:
# Imports at top of file
import os
import tarfile
# Actual code
with tarfile.open('NameOfArchive.tar.gz', 'w:gz') as tar:
for entry in os.scandir('directoryX'):
# Operates recursively on any directories, using the arcname as the base,
# so you add the whole tree just by adding all the entries in the top
# level directory. Using arcname of entry.name means it's equivalent to
# adding os.path.basename(entry.path), omitting all directory components
tar.add(entry.path, arcname=entry.name)
# The whole loop *could* be replaced with just:
# tar.add('directoryX', arcname='')
# which would add all contents recursively, but it would also put an entry
# for '/' in, which is undesirable
对于像这样的目录结构:
directoryX/
|
\- foo
\- bar
\- subdir/
|
\- spam
\- eggs
tar 的结果将是:
foo
bar
subdir/
subdir/eggs
subdir/spam
对比该:
./foo
./bar
./subdir/
./subdir/eggs
./subdir/spam
您当前的代码生成。
代码工作量稍微增加了一点,但没有那么更糟;两个导入和三行代码,并且可以更好地控制添加的内容(例如,您可以通过将 tar.add 调用包装在 if not entry.is_symlink(): 块中来轻松排除符号链接,或者通过有条件地设置 @ 来省略特定目录的递归添加987654352@ 到 tar.add 调用您不想包含其内容的目录;您甚至可以为 tar.add 调用提供 filter 函数,以有条件地排除特定条目,即使涉及深度递归)。