Erlang Thursday – erl_tar:create/2

今天的Erlang Thursday讲的是 erl_tar:create/2

erl_tar:create/2 根据传入的文件名来创建一个tar文件并将参提供的文件列表加入到tar文件里。

erl_tar:create/2 有两个入参,第一个入参是一个要写入内容到文件名,第二个入参是一个将要加入tar文件里的文件列表。

首先我们打开一个新的操作系统shell会话并且创建一些文件,这些文件将加入到一个新tar文件。

1
2
3
4
5
$ echo "foo" > foo.txt
$ echo "bar" > bar.txt
$ echo "baz" > baz.txt
$ ls
bar.txt baz.txt foo.txt test.tar

现在我们有了一些可以归档的文件,我们可以打开一个新的erl shell,并且创建一个新的tar文件,它的名字是test.tar。

1
2
erl_tar:create("test.tar", ["foo.txt", "bar.txt", "baz.txt"]).
% ok

看起来好像是有用的,所以我们回到OS shell,看看刚才我们给 erl_tar:create/2(译者注:作者手误写成了 erl_tar:create/3 ) 函数传的那个tar文件。

1
2
3
4
$ tar -tf test.tar
foo.txt
bar.txt
baz.txt

没错,tar可以读这个文件并且告诉我们,那三个我们传入的文件都真的在tar文件里。

erl_tar:create/3

Erlang也提供了 erl_tar:create/3 它最后一个入参是一个选项列表。

我们将创建一个新的tar文件,它里面的文件和上面的例子是一样的,第三个入参我们表明我们想要这个tar文件被压缩而且执行过程中在控制台输出执行过程的内容。

1
2
3
4
5
6
7
erl_tar:create("options.tar.gz",
["foo.txt", "bar.txt", "baz.txt"],
[compressed, verbose]).
% a foo.txt
% a bar.txt
% a baz.txt
% ok

再次回到OS shell,来看看这个tar文件里包含的文件。

1
2
3
4
$ tar -tf options.tar.gz
foo.txt
bar.txt
baz.txt

然后我们来测试一下,这个文件是否能被gzip解压缩。

1
2
$ gzip --test options.tar.gz
$

结果gzip认为这个文件压缩完整性很好。接着我们来看看我们创建的这两个tar文件在大小上的差异。

1
2
3
$ ls -l test.tar options.tar.gz
-rw-r--r-- 1 ------- ----- 154 Sep XX HH:MM options.tar.gz
-rw-r--r-- 1 ------- ----- 10240 Sep XX HH:MM test.tar

从文件大小来看,options.tar.gz 的确是被压缩的,因为它比test.tar小了两个数量级。

创建一个已经存在的文件

我们刚刚创建了 test.tar 并且看了它内部的内容。现在我们来看看传入相同的文件名test.tar和一个空的文件列表来创建一个已经存在的文件,这样做会发生什么。

1
2
erl_tar:create("test.tar", []).
% ok

然后我们看看它的内容,发现它原来的内容被替换了。

1
2
$ tar -tf test.tar
$

这说明,erl_tar:create/2 创建tar文件并且覆盖已经存在的文件,如果文件已经存在它不会输出错误(假设用户的shell有权限写该文件或目录)。

在一个不存在的路径上创建tar文件

如果我们给一个不存在的路径, 我们可以看到 erl_tar:create/2 将返回一个错误元组,包括了文件名以及错误原因。

1
2
erl_tar:create('/path/does/not/exist.tar', []).
% {error,{'/path/does/not/exist.tar',enoent}}

其他潜在的陷阱

首先官方文档说该函数入参是文件名,但是它没有指明erl_tar模块中文件名的数据类型是什么。

如果你用原子来做文件名,你会像我第一次用字符串做文件名前一样得到下面例子的错误。

1
2
3
4
5
6
7
erl_tar:create('test.tar', ['foo.txt', 'bar.txt', 'baz.txt']).
** exception error: no function clause matching filename:join([]) (filename.erl, line 392)
in function erl_tar:split_filename/4 (erl_tar.erl, line 423)
in call from erl_tar:create_header/3 (erl_tar.erl, line 352)
in call from erl_tar:add1/4 (erl_tar.erl, line 305)
in call from erl_tar:foreach_while_ok/2 (erl_tar.erl, line 940)
in call from erl_tar:create/3 (erl_tar.erl, line 114)

其次,根据erl_tar官方文档的 限制 这一节,为了最大的兼容性,在各种不同操作系统和tar程序版本中,文件名应该少于100个字符。

最后,当我们指定文件名的时候,包不包括扩展名由我们使用者决定,这和 erl_tar:compress/2 函数一样不为我们使用者管理文件扩展名。

原文链接: https://www.proctor-it.com/erlang-thursday-erl_tar-create-2/