查看源码 erl_tar (stdlib v6.2)
用于读取和写入 tar 归档的 Unix 'tar' 工具。
此模块将文件归档和提取到 tar 文件中。此模块支持读取大多数常见的 tar 格式,即 v7、STAR、USTAR 和 PAX,以及 GNU tar 对 USTAR 格式的一些扩展(最值得注意的是稀疏文件)。它生成 USTAR 格式的 tar 归档,除非要归档的文件由于 USTAR 的限制(例如 Unicode 元数据、文件名长度等)而需要 PAX 格式。因此,erl_tar
支持由大多数现代 tar 工具生成的 tar 归档,并生成应同样具有可移植性的 tarball。
按照惯例,tar 文件的名称应以 “.tar
” 结尾。为了遵守惯例,请将 “.tar
” 添加到名称中。
可以使用函数 create/2
或 create/3
在一个操作中创建 tar 文件。
或者,为了更好地控制,可以使用函数 open/2
、add/3,4
和 close/1
。
要从 tar 文件中提取所有文件,请使用函数 extract/1
。要仅提取某些文件或能够指定更多选项,请使用函数 extract/2
。
要返回 tar 文件中文件列表,请使用函数 table/1
或 table/2
。要将文件列表打印到 Erlang shell,请使用函数 t/1
或 tt/1
。
要将上述函数返回的错误项转换为可读的消息,请使用函数 format_error/1
。
Unicode 支持
如果 file:native_name_encoding/0
返回 utf8
,则在创建 tar 文件时,路径名将以 UTF-8 编码,并且在提取 tar 文件时,假定路径名以 UTF-8 编码。
如果 file:native_name_encoding/0
返回 latin1
,则不会进行路径名的转换。
PAX 标头中存储的 Unicode 元数据将保留
其他存储介质
ftp
模块通常使用 file
模块访问磁盘上的 tar 文件。当出现其他需求时,您可以定义自己的底层 Erlang 函数来在存储介质上执行写入和读取操作;请使用函数 init/3
。
这方面的一个示例是 ssh_sftp:open_tar/3
中的 SFTP 支持。此函数使用 SFTP 通道打开远程计算机上的 tar 文件。
限制
- 如果您必须与 USTAR tar 格式保持兼容,则必须确保存储的文件路径总共小于 255 字节,且最大文件名组件长度为 100 字节。USTAR 除了名称字段外,还使用标头字段(前缀),并将长于 100 字节的文件路径拆分为两个部分。这种拆分是在目录边界上进行的,并且以尽可能利用这两个字段中的可用空间的方式进行,但实际上,这通常意味着您用于路径的字节数少于 255 个。
erl_tar
将自动将格式升级为 PAX 以处理更长的文件名,因此,这仅在您需要使用不支持 PAX 的erl_tar
或tar
的旧版本提取归档时才成为问题。在这种情况下,PAX 标头将作为常规文件提取,您将需要手动应用它们。 - 与上述类似,如果您必须保持 USTAR 兼容,则还必须确保符号/硬链接的路径不超过 100 字节,否则将使用 PAX 标头。
摘要
函数
将文件添加到已通过 open/1
打开进行写入的 tar 文件。
关闭由 open/2
打开的 tar 文件。
创建 tar 文件并将名称在 FileList
中指定的文件归档到其中。这些文件可以从磁盘读取,也可以指定为二进制文件。
创建 tar 文件并将名称在 FileList
中指定的文件归档到其中。这些文件可以从磁盘读取,也可以指定为二进制文件。
从 tar 归档中提取所有文件。
从 tar 归档中提取文件。
将错误原因项转换为人类可读的错误消息字符串。
创建用于写入的 tar 文件(任何具有相同名称的现有文件都将被截断)。
将 tar 文件 Name
中所有文件的名称打印到 Erlang shell(类似于 “tar t
”)。
检索 tar 文件 Name
中所有文件的名称。
将 tar 文件 Name
中所有文件的名称和信息打印到 Erlang shell(类似于 “tar tv
”)。
类型
-type add_opt() :: dereference | verbose | {chunks, pos_integer()} | {atime, non_neg_integer()} | {mtime, non_neg_integer()} | {ctime, non_neg_integer()} | {uid, non_neg_integer()} | {gid, non_neg_integer()}.
-type create_opt() :: compressed | cooked | dereference | verbose.
-type extract_opt() :: {cwd, string()} | {files, [name_in_archive()]} | compressed | cooked | memory | keep_old_files | verbose.
-type file_op() :: fun((write | close | read2 | position, {user_data(), iodata()} | user_data() | {user_data(), non_neg_integer()} | {user_data(), non_neg_integer()}) -> ok | eof | {ok, string() | binary()} | {ok, non_neg_integer()} | {error, term()}).
-type filelist() :: [file:filename() | {name_in_archive(), file:filename_all()}].
-type gid() :: non_neg_integer().
-type mode() :: non_neg_integer().
-type name_in_archive() :: string().
-type open_type() :: file:filename_all() | {binary, binary()} | {file, file:io_device()}.
-opaque tar_descriptor()
-type tar_entry() :: {Name :: name_in_archive(), Type :: typeflag(), Size :: non_neg_integer(), MTime :: tar_time(), Mode :: mode(), Uid :: uid(), Gid :: gid()}.
-type tar_time() :: non_neg_integer().
-type typeflag() :: regular | link | symlink | char | block | directory | fifo | reserved | unknown.
-type uid() :: non_neg_integer().
-type user_data() :: term().
函数
-spec add(TarDescriptor, Name, Options) -> ok | {error, term()} when TarDescriptor :: tar_descriptor(), Name :: name_in_archive() | {name_in_archive(), file:filename_all()}, Options :: [add_opt()].
等效于 add/4
。
如果 Name
是 name_in_archive/0
,则调用 add(TarDescriptor, Name, Name, Options)
。
如果 Name
是一个二元组,则调用 add(TarDescriptor, NameInArchive, Name, Options)
。
-spec add(TarDescriptor, Filename, NameInArchive, Options) -> ok | {error, term()} when TarDescriptor :: tar_descriptor(), Filename :: file:filename_all(), NameInArchive :: name_in_archive(), Options :: [add_opt()].
将文件添加到已通过 open/1
打开进行写入的 tar 文件。
NameInArchive
是该文件在 tar 文件中存储的名称。当从 tar 文件中提取该文件时,它将获得此名称。
选项
dereference
- 默认情况下,符号链接在 tar 文件中存储为符号链接。要覆盖默认值并将符号链接指向的文件存储到 tar 文件中,请使用选项dereference
。verbose
- 打印有关添加文件的信息性消息。{chunks,ChunkSize}
- 从文件中分部分读取数据。这适用于内存受限的计算机,例如,在远程计算机上通过 SFTP 构建 tar 文件,请参阅ssh_sftp:open_tar/3
。{atime,non_neg_integer()}
- 设置上次读取文件的时间,以 POSIX 时间表示。另请参阅file:read_file_info/1
。{mtime,non_neg_integer()}
- 设置上次写入文件的时间,以 POSIX 时间表示。另请参阅file:read_file_info/1
。{ctime,non_neg_integer()}
- 设置文件创建的时间,以 POSIX 时间表示。另请参阅file:read_file_info/1
。{uid,non_neg_integer()}
- 设置文件所有者。file:read_file_info/1
。{gid,non_neg_integer()}
- 设置文件所有者所属的组。file:read_file_info/1
。
-spec close(TarDescriptor :: tar_descriptor()) -> ok | {error, term()}.
关闭由 open/2
打开的 tar 文件。
-spec create(file:filename_all(), filelist()) -> ok | {error, {string(), term()}}.
创建 tar 文件并将名称在 FileList
中指定的文件归档到其中。这些文件可以从磁盘读取,也可以指定为二进制文件。
-spec create(file:filename_all(), filelist(), [create_opt()]) -> ok | {error, term()} | {error, {string(), term()}}.
创建 tar 文件并将名称在 FileList
中指定的文件归档到其中。这些文件可以从磁盘读取,也可以指定为二进制文件。
OptionList
中的选项按如下方式修改默认值
compressed
- 整个 tar 文件被压缩,就像已通过gzip
程序运行一样。为了遵守压缩 tar 文件应以 “.tar.gz
” 或 “.tgz
” 结尾的惯例,请添加适当的扩展名。cooked
- 默认情况下,函数open/2
以raw
模式打开 tar 文件,这种模式速度更快,但不允许使用远程 (Erlang) 文件服务器。将cooked
添加到模式列表会覆盖默认设置,并在不使用raw
选项的情况下打开 tar 文件。dereference
- 默认情况下,符号链接在 tar 文件中存储为符号链接。要覆盖默认值并将符号链接指向的文件存储到 tar 文件中,请使用选项dereference
。verbose
- 打印有关每个添加文件的信息消息。
从 tar 归档中提取所有文件。
如果参数 Name
被指定为 {binary,Binary}
,则假定二进制文件的内容是 tar 归档文件。
如果参数 Name
被指定为 {file,Fd}
,则假定 Fd
是从函数 file:open/2
返回的文件描述符。
否则,Name
应为文件名。
注意
在写入文件之前,tar 成员名称中的前导斜杠将被删除。也就是说,绝对路径将转换为相对路径。当以这种方式更改路径时,会向错误记录器写入一条信息消息。
警告
当使用
{file,Fd}
传递文件描述符时,compressed
和cooked
标志无效。假定文件已使用适当的标志打开。
-spec extract(Open :: open_type(), [extract_opt()]) -> {ok, [{string(), binary()}]} | {error, term()} | ok.
从 tar 归档中提取文件。
如果参数 Name
被指定为 {binary,Binary}
,则假定二进制文件的内容是 tar 归档文件。
如果参数 Name
被指定为 {file,Fd}
,则假定 Fd
是从函数 file:open/2
返回的文件描述符。
否则,Name
应为文件名。
以下选项修改了提取的默认设置,如下所示
{cwd,Cwd}
- 默认情况下,具有相对文件名的文件会提取到当前工作目录。使用此选项,文件将改为提取到目录Cwd
。{files,FileList}
- 默认情况下,所有文件都会从 tar 文件中提取。使用此选项,仅提取名称包含在FileList
中的文件。compressed
- 使用此选项,将在提取时解压缩文件。如果 tar 文件未压缩,则忽略此选项。cooked
- 默认情况下,函数open/2
以raw
模式打开 tar 文件,这种模式速度更快,但不允许使用远程 (Erlang) 文件服务器。将cooked
添加到模式列表会覆盖默认设置,并在不使用raw
选项的情况下打开 tar 文件。memory
- 此选项不会提取到目录,而是将结果作为元组列表{Filename, Binary}
给出,其中Binary
是一个二进制文件,其中包含 tar 文件中名为Filename
的文件的提取数据。keep_old_files
- 默认情况下,所有与 tar 文件中文件名相同的文件将被覆盖。使用此选项,现有文件不会被覆盖。verbose
- 为每个提取的文件打印一条信息消息。
警告
当使用
{file,Fd}
传递文件描述符时,compressed
和cooked
标志无效。假定文件已使用适当的标志打开。
将错误原因项转换为人类可读的错误消息字符串。
-spec init(UserData :: user_data(), write | read, file_op()) -> {ok, tar_descriptor()} | {error, badarg}.
Fun
是定义在从较高 tar 处理函数(如 add/3
、add/4
和 close/1
)调用不同的存储操作函数时要执行的操作。
当 tar 函数想要执行低级操作(例如将块写入文件)时,将调用 Fun
。Fun
的调用方式为 Fun(Op, {UserData,Parameters...})
,其中 Op
是操作名称,UserData
是作为第一个参数传递给 init/1
的项,Parameters...
是 tar 函数添加的要传递给存储处理函数的数据。
参数 UserData
通常是打开低级结构(如文件描述符或 SFTP 通道 ID)的结果。不同的 Fun
子句对该项进行操作。
以下是 fun 子句参数列表
(write, {UserData,DataToWrite})
- 使用UserData
写入项DataToWrite
。(close, UserData)
- 关闭访问。(read2, {UserData,Size})
- 使用UserData
读取,但仅读取Size
个字节。请注意,只有一个 arity-2 读取函数,而不是 arity-1 函数。(position,{UserData,Position})
- 设置UserData
的位置,如file:position/2
中为文件定义的那样
示例
以下是使用 file
模块在文件上进行读取和写入的完整 Fun
参数
ExampleFun =
fun(write, {Fd,Data}) -> file:write(Fd, Data);
(position, {Fd,Pos}) -> file:position(Fd, Pos);
(read2, {Fd,Size}) -> file:read(Fd, Size);
(close, Fd) -> file:close(Fd)
end
此处,Fd
已指定给函数 init/3
,如下所示
{ok,Fd} = file:open(Name, ...).
{ok,TarDesc} = erl_tar:init(Fd, [write], ExampleFun),
然后使用 TarDesc
erl_tar:add(TarDesc, SomeValueIwantToAdd, FileNameInTarFile),
...,
erl_tar:close(TarDesc)
当 erl_tar
核心想要执行操作(例如,写入一段 Data
)时,它会调用 ExampleFun(write, {UserData,Data})
。
注意
此示例使用
file
模块操作不是必须直接使用的,因为这原则上是函数open/2
所做的事情。
警告
TarDescriptor
项不是文件描述符。建议您不要依赖此项的具体内容,因为当此模块添加更多功能时,它可能会在未来的 Erlang/OTP 版本中更改。
-spec open(Open :: open_type(), [write | compressed | cooked]) -> {ok, tar_descriptor()} | {error, term()}.
创建用于写入的 tar 文件(任何具有相同名称的现有文件都将被截断)。
按照惯例,tar 文件的名称应以 “.tar
” 结尾。为了遵守惯例,请将 “.tar
” 添加到名称中。
除了 write
原子外,以下原子可以添加到 OpenModeList
compressed
- 整个 tar 文件被压缩,就像已通过gzip
程序运行一样。为了遵守压缩 tar 文件应以 “.tar.gz
” 或 “.tgz
” 结尾的惯例,请添加适当的扩展名。cooked
- 默认情况下,tar 文件以raw
模式打开,这种模式速度更快,但不允许使用远程 (Erlang) 文件服务器。将cooked
添加到模式列表会覆盖默认设置,并在不使用raw
选项的情况下打开 tar 文件。
要一次向打开的 tar 文件中添加一个文件,请使用函数 add/3,4
。添加完文件后,请使用函数 close/1
关闭 tar 文件。
警告
当使用
{file,Fd}
传递文件描述符时,compressed
和cooked
标志无效。文件必须已使用适当的标志打开。
警告
TarDescriptor
项不是文件描述符。建议您不要依赖此项的具体内容,因为当此模块添加更多功能时,它可能会在未来的 Erlang/OTP 版本中更改。
-spec t(file:filename()) -> ok | {error, term()}.
将 tar 文件 Name
中所有文件的名称打印到 Erlang shell(类似于 “tar t
”)。
-spec table(Open :: open_type()) -> {ok, [name_in_archive()]} | {error, term()}.
等效于 table(Open, [])
。
-spec table(Open :: open_type(), [compressed | verbose | cooked]) -> {ok, [name_in_archive() | tar_entry()]} | {error, term()}.
检索 tar 文件 Name
中所有文件的名称。
将 tar 文件 Name
中所有文件的名称和信息打印到 Erlang shell(类似于 “tar tv
”)。