目录

名称

Archive::Tar - 处理 tar 存档的模块

概要

use Archive::Tar;
my $tar = Archive::Tar->new;

$tar->read('origin.tgz');
$tar->extract();

$tar->add_files('file/foo.pl', 'docs/README');
$tar->add_data('file/baz.txt', 'This is the contents now');

$tar->rename('oldname', 'new/file/name');
$tar->chown('/', 'root');
$tar->chown('/', 'root:root');
$tar->chmod('/tmp', '1777');

$tar->write('files.tar');                   # plain tar
$tar->write('files.tgz', COMPRESS_GZIP);    # gzip compressed
$tar->write('files.tbz', COMPRESS_BZIP);    # bzip2 compressed
$tar->write('files.txz', COMPRESS_XZ);      # xz compressed

说明

Archive::Tar 提供了一种面向对象机制来处理 tar 文件。它提供类方法来快速轻松地处理文件,同时还允许创建 tar 文件对象以进行自定义操作。如果您安装了 IO::Zlib 模块,Archive::Tar 还将支持压缩或 gzip 压缩的 tar 文件。

Archive::Tar 类的对象表示一个包含文件和事物的 .tar(.gz) 存档。

对象方法

Archive::Tar->new( [$file, $compressed] )

返回一个新的 Tar 对象。如果给出了任何参数,new() 会自动调用 read() 方法,并将提供给 read() 方法的参数传递过去。

如果 new() 被调用时带有参数,并且 read() 方法因任何原因而失败,new() 会返回 undef。

$tar->read ( $filename|$handle, [$compressed, {opt => 'val'}] )

将给定的 tar 文件读入内存。第一个参数可以是文件名称或对已打开的文件句柄的引用(如果压缩,则为 IO::Zlib 对象)

read替换$tar 中的任何先前内容!

第二个参数可以被认为是可选的,但保留是为了向后兼容。Archive::Tar 现在会查看文件魔术,以确定应该使用哪个类来打开文件,并将透明地执行正确操作。

如果您尝试传递 bzip2 / xz 压缩文件,并且 IO::Uncompress::Bunzip2 / IO::Uncompress::UnXz 不可用的情况下,Archive::Tar 会发出警告,然后直接返回。

请注意,您目前不能传递使用 IO::Zlib 打开的 gzip 压缩文件句柄、使用 IO::Uncompress::Bunzip2 打开的 bzip2 压缩文件句柄、使用 IO::Uncompress::UnXz 打开的 xz 压缩文件句柄,也不能传递包含完整存档信息(压缩或未压缩)的字符串。这些都是有价值的功能,但目前尚未实现。请参阅 TODO 部分。

第三个参数可以是带有选项的哈希引用。请注意,所有选项都区分大小写。

limit

不要读取超过 limit 个文件。如果您有非常大的存档,并且只对前几个文件感兴趣,这将很有用。

filter

可以设置为正则表达式。只有名称与该表达式匹配的文件才会被读取。

md5

设置为 1,将返回文件的 md5sum(而不是文件数据)my $iter = Archive::Tar->iter( $file, 1, {md5 => 1} ); while( my $f = $iter->() ) { print $f->data . "\t" . $f->full_path . $/; }

extract

如果设置为 true,则在读取条目时立即解压它们。这会为您提供与 extract_archive 函数相同的内存中断。但请注意,不会将条目读入内存,而是直接写入磁盘。这意味着不会为您创建 Archive::Tar::File 对象以供您检查。

所有文件在内部都存储为 Archive::Tar::File 对象。有关详细信息,请参阅 Archive::Tar::File 文档。

在标量上下文中返回读取的文件数,在列表上下文中返回 Archive::Tar::File 对象的列表。

$tar->contains_file( $filename )

检查存档是否包含某个文件。如果存档中存在该文件,则返回 true,否则返回 false。

但请注意,此函数使用 eq 对完整路径执行精确匹配。因此,它无法补偿不区分大小写的文件系统或比较 2 个路径以查看它们是否指向同一底层文件。

$tar->extract( [@filenames] )

将名称等效于 @filenames 中任何名称的文件写入磁盘,并根据需要创建子目录。这在 VMS 下可能不太好用。在 MacPerl 下,文件的修改时间将转换为 MacOS 时间零,并且会对路径执行适当的转换。但是,不会检查路径中每个元素的长度是否超过 MacOS 当前允许的长度(32 个字符)。

如果在没有文件名列表的情况下调用 extract,则会解压存档的全部内容。

返回解压的文件名的列表。

$tar->extract_file( $file, [$extract_path] )

将名称等效于提供的文件名的条目写入磁盘。还可以选择第二个参数,该参数是条目将被写入的完整本机路径(包括文件名)。

例如

$tar->extract_file( 'name/in/archive', 'name/i/want/to/give/it' );

$tar->extract_file( $at_file_object,   'name/i/want/to/give/it' );

成功时返回 true,失败时返回 false。

$tar->list_files( [\@properties] )

返回存档中所有文件的名称列表。

如果将数组引用作为第一个参数传递给 list_files(),它将返回一个哈希引用的列表,其中包含每个文件的请求属性。支持以下属性列表:名称、大小、mtime(上次修改日期)、模式、uid、gid、linkname、uname、gname、devmajor、devminor、prefix。

传递仅包含一个元素“名称”的数组引用是特殊情况,它返回名称列表而不是哈希引用的列表,使其等效于调用不带参数的 list_files

$tar->get_files( [@filenames] )

返回与提供的文件名匹配的 Archive::Tar::File 对象。如果没有传递文件名列表,则返回当前 Tar 对象中的所有 Archive::Tar::File 对象。

请参阅 Archive::Tar::File 文档,了解如何处理这些对象。

$tar->get_content( $file )

返回指定文件的内容。

$tar->replace_content( $file, $content )

使字符串 $content 成为名为 $file 的文件的内容。

$tar->rename( $file, $new_name )

将内存存档的文件重命名为 $new_name。

请注意,你必须为 $new_name 指定 Unix 路径,因为根据 tar 标准,存档中的所有文件都必须是 Unix 路径。

成功时返回 true,失败时返回 false。

$tar->chmod( $file, $mode )

将 $file 的模式更改为 $mode。

成功时返回 true,失败时返回 false。

$tar->chown( $file, $uname [, $gname] )

将所有者 $file 更改为 $uname 和 $gname。

成功时返回 true,失败时返回 false。

$tar->remove (@filenamelist)

从内存存档中移除与任何指定文件名匹配的任何条目。返回剩余的 Archive::Tar::File 对象的列表。

$tar->clear

clear 清除当前内存存档。这实际上会提供一个“空白”对象,准备再次填充。请注意,clear 仅对对象有效,而不对基础 tar 文件有效。

$tar->write ( [$file, $compressed, $prefix] )

将内存存档写入磁盘。第一个参数可以是文件名称,也可以是对已打开文件句柄(GLOB 引用)的引用。

第二个参数用于指示压缩。可以使用 gzipbzip2xz 进行压缩。如果您传递一个数字,则假定它是 gzip 压缩级别(介于 1 和 9 之间),但首选使用常量

# write a gzip compressed file
$tar->write( 'out.tgz', COMPRESS_GZIP );

# write a bzip compressed file
$tar->write( 'out.tbz', COMPRESS_BZIP );

# write a xz compressed file
$tar->write( 'out.txz', COMPRESS_XZ );

请注意,当您传递文件句柄时,将忽略压缩参数,因为所有文件都会逐字打印到您的文件句柄。如果您希望使用文件句柄启用压缩,请改用 IO::ZlibIO::Compress::Bzip2IO::Compress::Xz 文件句柄。

第三个参数是一个可选前缀。所有文件都将被保存在您指定为前缀的目录中。因此,如果您在存档中具有文件“a”和“b”,并且指定“foo”作为前缀,它们将作为“foo/a”和“foo/b”写入存档。

如果没有给出参数,write 将返回整个格式化的存档作为字符串,如果您想将存档塞入套接字或管道以进行 gzip 或其他操作,这可能很有用。

$tar->add_files( @filenamelist )

获取文件名列表并将它们添加到内存存档中。

文件路径会自动转换为类似 Unix 的等效路径以用于存档中,并且,如果在 MacOS 上,文件的修改时间会从 MacOS 纪元转换为 Unix 纪元。因此,使用 Archive::Tar 在 MacOS 上创建的 tar 存档既可以在 Unix 上使用 tar 读取,也可以在 MacOS 上使用 suntarStuffit Expander 等应用程序读取。

请注意,文件的类型/创建者和资源分支将丢失,这通常是跨平台存档中所需的内容。

除了文件名,您还可以传递现有的 Archive::Tar::File 对象,例如,从另一个存档中。该对象将被克隆,实际上是原始对象的副本,而不是别名。

返回刚添加的 Archive::Tar::File 对象列表。

$tar->add_data ( $filename, $data, [$opthashref] )

获取一个文件名、一个包含完整数据的标量,以及一个指向具有特定选项的哈希的引用(可选)。

将一个文件添加到内存存档中,名称为 $filename,内容为 $data。可以使用 $opthashref 设置特定属性。支持以下属性列表:名称、大小、mtime(上次修改日期)、模式、uid、gid、linkname、uname、gname、devmajor、devminor、prefix、type。(在 MacOS 上,文件的路径和修改时间将转换为 Unix 等效项。)

文件类型的有效值为 Archive::Tar::Constant 定义的以下常量

FILE

常规文件。

硬链接和符号链接(“软”链接);linkname 应指定目标。

CHARDEV
BLOCKDEV

字符设备和块设备。devmajor 和 devminor 应指定主设备号和次设备号。

DIR

目录。

FIFO

FIFO(命名管道)。

SOCKET

套接字。

返回刚添加的 Archive::Tar::File 对象,或在失败时返回 undef

$tar->error( [$BOOL] )

返回当前错误字符串(通常是报告的最后一个错误)。如果指定了 true 值,它将提供错误的 Carp::longmess 等效项,实际上会为您提供堆栈跟踪。

为了向后兼容,此错误也可用作 $Archive::Tar::error,尽管强烈建议您改用方法调用。

$tar->setcwd( $cwd );

Archive::Tar 需要知道当前目录,并且它将在每次从 tar 文件中提取一个相对条目并将其保存在文件系统中时运行 Cwd::cwd()。 (然而,从 1.30 版开始,Archive::Tar 将自动使用下面描述的速度优化,因此只有在您使用 extract_file() 时才相关。)

由于 Archive::Tar 在提取 tar 包中的项目时不会在内部更改当前目录,因此如果我们能保证当前目录不会在外部更改,则可以避免所有对 Cwd::cwd() 的调用。

若要使用此性能提升,请通过以下方式设置当前目录

use Cwd;
$tar->setcwd( cwd() );

在调用 extract_fileArchive::Tar 等函数之前调用一次,将从那时起使用当前目录设置,并且不会在内部调用 Cwd::cwd()

若要切换回默认行为,请使用

$tar->setcwd( undef );

Archive::Tar 将再次在内部调用 Cwd::cwd()

如果您正在使用 Archive::Tarextract() 方法,则会为您调用 setcwd()

类方法

Archive::Tar->create_archive($file, $compressed, @filelist)

从提供的文件列表创建 tar 文件。第一个参数可以是创建的 tar 文件的名称或对打开的文件句柄的引用(例如,GLOB 引用)。

第二个参数用于指示压缩。可以使用 gzipbzip2xz 进行压缩。如果您传递一个数字,则假定它是 gzip 压缩级别(介于 1 和 9 之间),但首选使用常量

# write a gzip compressed file
Archive::Tar->create_archive( 'out.tgz', COMPRESS_GZIP, @filelist );

# write a bzip compressed file
Archive::Tar->create_archive( 'out.tbz', COMPRESS_BZIP, @filelist );

# write a xz compressed file
Archive::Tar->create_archive( 'out.txz', COMPRESS_XZ, @filelist );

请注意,当您传递文件句柄时,将忽略压缩参数,因为所有文件都会逐字打印到您的文件句柄。如果您希望使用文件句柄启用压缩,请改用 IO::ZlibIO::Compress::Bzip2IO::Compress::Xz 文件句柄。

其余参数列出要包含在 tar 文件中的文件。这些文件必须全部存在。任何不存在或无法读取的文件都将被静默忽略。

如果由于任何原因导致归档创建失败,则 create_archive 将返回 false。请使用 error 方法查找失败原因。

请注意,此方法不会像以前那样“即时”写入;它仍然会在写出归档之前将所有文件读入内存。如果这是一个问题,请参阅下面的常见问题解答。

Archive::Tar->iter( $filename, [ $compressed, {opt => $val} ] )

返回一个迭代函数,该函数读取 tar 文件而不将其全部加载到内存中。每次调用该函数时,它将返回 tar 包中的下一个文件。文件作为 Archive::Tar::File 对象返回。迭代函数在耗尽所包含的文件后返回空列表。

第二个参数可以是包含选项的哈希引用,这些选项与传递给 read() 的参数相同。

示例用法

my $next = Archive::Tar->iter( "example.tar.gz", 1, {filter => qr/\.pm$/} );

while( my $f = $next->() ) {
    print $f->name, "\n";

    $f->extract or warn "Extraction failed";

    # ....
}

Archive::Tar->list_archive($file, $compressed, [\@properties])

返回归档中所有文件的名称列表。第一个参数可以是列出的 tar 文件的名称或对打开的文件句柄的引用(例如,GLOB 引用)。

如果 list_archive() 将数组引用作为其第三个参数传递,则它将返回一个哈希引用的列表,其中包含每个文件的请求属性。支持以下属性列表:full_path、name、size、mtime(上次修改日期)、mode、uid、gid、linkname、uname、gname、devmajor、devminor、prefix、type。

有关支持的属性的详细信息,请参阅 Archive::Tar::File

传递仅包含一个元素“name”的数组引用,将作为特殊情况处理,返回名称列表,而不是哈希引用的列表。

Archive::Tar->extract_archive($file, $compressed)

解压 tar 文件的内容。第一个参数可以是创建的 tar 文件的名称,也可以是对打开文件句柄的引用(例如 GLOB 引用)。tar 文件中的所有相对路径都将在当前工作目录下创建。

extract_archive 将返回它解压的文件列表。如果由于任何原因归档解压失败,extract_archive 将返回 false。请使用 error 方法查找失败的原因。

$bool = Archive::Tar->has_io_string

如果当前已加载 IO::String 支持,则返回 true。

需要 IO::Stringperlio 支持才能支持编写字符串化归档文件。目前,perlio 是首选方法(如果可用)。

请参阅 全局变量 部分,了解如何更改此首选项。

$bool = Archive::Tar->has_perlio

如果当前已加载 perlio 支持,则返回 true。

这需要 perl-5.8 或更高版本,并使用 perlio 编译

需要 IO::Stringperlio 支持才能支持编写字符串化归档文件。目前,perlio 是首选方法(如果可用)。

请参阅 全局变量 部分,了解如何更改此首选项。

$bool = Archive::Tar->has_zlib_support

如果 Archive::Tar 可以解压 zlib 压缩的归档文件,则返回 true

$bool = Archive::Tar->has_bzip2_support

如果 Archive::Tar 可以解压 bzip2 压缩的归档文件,则返回 true

$bool = Archive::Tar->has_xz_support

如果 Archive::Tar 可以解压 xz 压缩的归档文件,则返回 true

Archive::Tar->can_handle_compressed_files

一个简单的检查例程,如果 Archive::Tar 能够使用 IO::ZlibIO::Compress::Bzip2IO::Compress::Xz 即时解压缩压缩归档文件,则返回 true;如果两者都未安装,则返回 false。

在将压缩归档文件传递给其 read 方法之前,你可以使用此方法作为快捷方式来确定 Archive::Tar 是否会执行你认为它会执行的操作。

全局变量

将此变量设置为 1,以使 Archive::Tar 在解压时有效地复制文件。默认值为 0,这意味着符号链接保持不变。当然,你还必须打包链接到的文件。

当使用 writecreate_archive 写出 tar 文件时,选中此选项。

此选项的工作方式与 /bin/tar-h 选项类似。

$Archive::Tar::CHOWN

默认情况下,Archive::Tar 会尝试在能够时对文件执行 chown 操作。在某些情况下,这可能不是必需的。在这种情况下,将此变量设置为 0 以禁用 chown 操作,即使有可能执行该操作。

默认值为 1

$Archive::Tar::CHMOD

默认情况下,Archive::Tar 会尝试将文件 chmod 为存档中针对特定文件指定的任何模式。在某些情况下,这可能不是必需的。在这种情况下,将此变量设置为 0 以禁用 chmod 操作。

默认值为 1

$Archive::Tar::SAME_PERMISSIONS

当启用 $Archive::Tar::CHMOD 时,此设置控制是否使用存档中文件的权限,而不修改它们,或者通过删除任何 setid 位并应用当前 umask 来过滤它们。

对于 root 用户,默认值为 1,对于普通用户,默认值为 0

$Archive::Tar::DO_NOT_USE_PREFIX

默认情况下,Archive::Tar 会尝试将超过 100 个字符的路径放入 tar 头的 prefix 字段中,如 POSIX 标准所定义。但是,一些(较旧的)tar 程序未实现此规范。为了与这些旧版本或不兼容 POSIX 的版本保持兼容性,可以将 $DO_NOT_USE_PREFIX 变量设置为 true 值,而 Archive::Tar 将通过使用 GNU Extended Header 功能来处理超过 100 个字符的路径的替代方法。

请注意,不支持 GNU Extended Header 功能的客户端将无法读取这些存档。此类客户端包括 SolarisIrixAIX 上的 tar。

默认值为 0

$Archive::Tar::DEBUG

将此变量设置为 1 以始终获取警告的 Carp::longmess 输出,而不是常规的 carp。这是通过执行以下操作可以获得的相同消息

$tar->error(1);

默认为 0

$Archive::Tar::WARN

如果您不希望打印任何警告,请将此变量设置为 0。我个人建议不要这样做,但有人要求提供此选项。此外,请注意,这当然不是线程安全的。

默认为 1

$Archive::Tar::error

保存最后报告的错误。出于历史原因而保留,但强烈建议不要使用。改用 error() 方法

warn $tar->error unless $tar->extract;

请注意,在此模块的旧版本中,error() 方法即使在上述情况下作为实例方法调用,也会返回一个有效的全局值。此问题已得到修复,现在 Archive::Tar 的多个实例具有单独的错误字符串。

$Archive::Tar::INSECURE_EXTRACT_MODE

此变量指示 Archive::Tar 是否允许将文件解压到当前工作目录之外。

允许这样做可能会产生安全隐患,因为恶意 tar 存档可以更改或替换解压用户有权访问的任何文件。因此,默认情况下不允许不安全的解压。

如果您信任存档,或有其他原因允许存档将文件写入当前工作目录之外,请将此变量设置为 true

请注意,这是与 1.36 及更早版本相比向后不兼容的更改。

$Archive::Tar::HAS_PERLIO

此变量保存一个布尔值,指示我们当前是否加载了 perlio 支持。对于任何使用 perlio 编译的 perl 大于 5.8 的版本,此功能都将启用。

如果您强烈希望禁用它,请将此变量设置为 false。请注意,您随后需要安装 IO::String 来支持编写字符串化存档。

除非您确实知道自己在做什么,否则不要更改此变量。

$Archive::Tar::HAS_IO_STRING

此变量保存一个布尔值,指示我们当前是否加载了 IO::String 支持。对于任何具有可加载 IO::String 模块的 perl,此功能都将启用。

如果您强烈希望禁用它,请将此变量设置为 false。请注意,您随后需要从 perl 中获得 perlio 支持,才能编写字符串化存档。

除非您确实知道自己在做什么,否则不要更改此变量。

$Archive::Tar::ZERO_PAD_NUMBERS

此变量保存一个布尔值,指示我们是否将为 sizemtimechecksum 创建零填充数字。默认值为 0,表示我们将创建空格填充数字。添加此功能是为了与 busybox 实现兼容。

	You can tune the behaviour by setting the $Archive::Tar::RESOLVE_SYMLINK variable,
	or $ENV{PERL5_AT_RESOLVE_SYMLINK} before loading the module Archive::Tar.

  Values can be one of the following:

		none
           Disable this mechanism and failed as it was in previous version (<1.88)

		speed (default)
           If you prefer speed
           this will read again the whole archive using read() so all entries
           will be available

    memory
           If you prefer memory

	Limitation

		It won't work for terminal, pipe or sockets or every non seekable source.

常见问题解答

运行 Archive::Tar 所需的 perl 最低版本是什么?

您需要 perl 版本 5.005_03 或更高版本。

Archive::Tar 速度是不是很慢?

是的,确实很慢。它完全基于 perl,因此比 /bin/tar 慢很多。但是,它的可移植性非常好。如果速度是个问题,请考虑改用 /bin/tar

Archive::Tar 的内存占用是不是比 /bin/tar 大?

是的,确实更大,请参阅上一个答案。由于 Compress::Zlib 以及 IO::Zlib 不支持对其文件句柄执行 seek,因此几乎别无选择,只能将存档读入内存。如果您想在内存中操作存档,这是可以的。

如果您只想解压,请改用 extract_archive 类方法。它将优化并立即写入磁盘。

另一个选择是使用 iter 类方法来遍历 tar 包中的文件,而无需一次性将它们全部读入内存。

您能否改为延迟加载数据?

在某些情况下,可以。您可以使用 iter 类方法来遍历 tar 包中的文件,而无需一次性将它们全部读入内存。

一个 X kb 的 tar 文件需要多少内存?

可能需要超过 X kb,因为所有内容都将读入内存。如果这是一个问题,并且您不需要在内存中操作存档,请考虑改用 iter 类方法或 /bin/tar

如何处理存档中不受支持的文件类型?

Unix 有一些在其他平台(如 Win32)上不受支持的文件类型。如果我们遇到 hardlinksymlink,我们将尝试复制原始文件,而不是抛出错误。

这确实要求您先将整个存档读入内存,因为否则我们不知道用什么数据填充副本。(这意味着您不能对具有不兼容文件类型的存档使用类方法(包括 iter),并且仍然希望一切正常工作)。

对于其他文件类型(如 chardevsblockdevs),我们会警告您此特定项目的解压未成功。

我正在使用 WinZip 或其他非 POSIX 客户端,并且文件未正确解压!

默认情况下,Archive::Tar 处于完全兼容 POSIX 的模式,该模式使用 tar 的 POSIX 规范来存储文件。对于大于 100 个字符的路径,这是使用 POSIX 头前缀 完成的。不兼容 POSIX 的客户端可能不支持规范的这一部分,并且可能仅支持 GNU 扩展头 功能。为了方便这些客户端,您可以将 $Archive::Tar::DO_NOT_USE_PREFIX 变量设置为 true。有关此变量的详细信息,请参阅 全局变量 部分。

请注意,早于 1.14 版本的 GNU tar 无法很好地处理 POSIX 头前缀。如果您使用此类版本,请考虑将 $Archive::Tar::DO_NOT_USE_PREFIX 变量设置为 true

如何从归档中仅提取具有属性 X 的文件?

有时,您可能不希望提取完整的归档文件,而只是根据某些条件提取与您相关的文件。

您可以通过根据条件筛选 Archive::Tar::File 对象列表来执行此操作。例如,要仅提取标题中包含字符串 foo 的文件,您将使用

$tar->extract(
    grep { $_->full_path =~ /foo/ } $tar->get_files
);

通过这种方式,您可以筛选归档文件中文件的任何属性。查阅 Archive::Tar::File 文档,了解如何使用这些对象。

如何访问 .tar.Z 文件?

Archive::Tar 模块可以选择使用 Compress::Zlib(通过 IO::Zlib 模块)来访问已使用 gzip 压缩的 tar 文件。不幸的是,Compress::Zlib 无法读取使用 Unix compress 实用程序压缩的 tar 文件,因此 Archive::Tar 无法直接访问它们。

如果 uncompressgunzip 程序可用,您可以使用以下一种解决方法从 Archive::Tar 读取 .tar.Z 文件

首先使用 uncompress

use Archive::Tar;

open F, "uncompress -c $filename |";
my $tar = Archive::Tar->new(*F);
...

然后使用 gunzip

use Archive::Tar;

open F, "gunzip -c $filename |";
my $tar = Archive::Tar->new(*F);
...

类似地,如果 compress 程序可用,您可以使用它来编写 .tar.Z 文件

use Archive::Tar;
use IO::File;

my $fh = IO::File->new( "| compress -c >$filename" );
my $tar = Archive::Tar->new();
...
$tar->write($fh);
$fh->close ;
如何处理 Unicode 字符串?

Archive::Tar 对从磁盘读取或写入到磁盘的任何文件使用字节语义。如果您只处理文件,从不查看其内容或仅使用字节字符串,则这不是问题。但是,如果您使用具有字符语义的 Unicode 字符串,则需要采取一些其他步骤。

例如,如果您添加一个 Unicode 字符串,如下所示

# Problem
$tar->add_data('file.txt', "Euro: \x{20AC}");

那么稍后当 tar 文件通过 $tar->write() 写入磁盘时,会出现问题

Wide character in print at .../Archive/Tar.pm line 1014.

数据以 Unicode 字符串形式添加,当将其写入磁盘时,Archive::Tar 未设置 :utf8 行规,因此 Perl 尝试将字符串转换为 ISO-8859 并失败。现在,已写入的文件包含垃圾。

因此,在将 Unicode 字符串传递给 add_data() 之前,需要将其转换为 UTF-8 编码的字节串。

use Encode;
my $data = "Accented character: \x{20AC}";
$data = encode('utf8', $data);

$tar->add_data('file.txt', $data);

如果您从 tar 包中提取 UTF8 编码的文件,则会出现相反的问题。对 Archive::Tar::File 对象使用 get_content() 将以字节串形式返回其内容,而不是以 Unicode 字符串形式返回。

如果您希望它成为 Unicode 字符串(因为您希望在正则表达式匹配等操作中使用字符语义),则需要对 UTF8 编码的内容进行解码,并让 Perl 将其转换为 Unicode 字符串

use Encode;
my $data = $tar->get_content();

# Make it a Unicode string
$data = decode('utf8', $data);

Archive::Tar 中没有提供此功能的简单方法,因为 tar 包可以包含许多文件,并且每个文件都可以以不同的方式进行编码。

注意事项

AIX tar 不会使用 0x00 填充 tar 归档中的所有未使用空间。这有时会导致 Archive::Tar 发出警告消息。

Invalid header block at offset nnn

计划在以下 AIX 级别中发布此问题的修复程序,所有这些级别都应在 2009 年第 4 季度发布

AIX 5.3 TL7 SP10
AIX 5.3 TL8 SP8
AIX 5.3 TL9 SP5
AIX 5.3 TL10 SP2

AIX 6.1 TL0 SP11
AIX 6.1 TL1 SP7
AIX 6.1 TL2 SP6
AIX 6.1 TL3 SP3

此问题的 IBM APAR 编号为 IZ50240(报告的组件 ID:5765G0300 / AIX 5.3)。可以为此问题获取 ifix。如果您需要 ifix,请联系您当地的 IBM AIX 支持人员。

待办事项

检查传入的句柄是否已打开以进行读/写

目前,我不知道有任何可移植的纯 perl 方法可以做到这一点。欢迎提出建议。

允许将归档文件作为字符串传入

目前,我们只允许打开的文件句柄或文件名,而不允许字符串。内部需要进行一些返工以方便字符串化归档。

方便处理压缩归档的打开文件句柄

目前,我们仅在文件句柄是 IO::Zlib 对象时支持此功能。像 apache 这样的环境会向您提供已上传文件的打开文件句柄,该文件可能是压缩归档文件。

另请参阅

GNU tar 规范

http://www.gnu.org/software/tar/manual/tar.html

PAX 格式规范

tar 派生的规范;http://www.opengroup.org/onlinepubs/007904975/utilities/pax.html

GNU 和 POSIX tar 标准的比较;http://www.delorie.com/gnu/docs/tar/tar_114.html
GNU tar 打算切换到 POSIX 兼容性

GNU Tar 作者已表示他们打算完全兼容 POSIX;http://www.gnu.org/software/tar/manual/html_node/Formats.html

各种 tar 实现之间的比较

列出已知问题和不兼容性;http://gd.tuwien.ac.at/utils/archivers/star/README.otherbugs

作者

此模块由 Jos Boumans <[email protected]> 编写。

请将错误报告至 <[email protected]>。

致谢

感谢 Sean Burke、Chris Nandor、Chip Salzenberg、Tim Heaney、Gisle Aas、Rainer Tammer,尤其是 Andrew Savige,感谢他们提供的帮助和建议。

版权

此模块的版权归 Jos Boumans <[email protected]> 所有 (c) 2002 - 2009。保留所有权利。

此库是免费软件;您可以在与 Perl 自身相同的条款下重新分发和/或修改它。