如何将目录添加到 tar 存档中的文件前面?

如何将目录添加到 tar 存档中的文件前面?

我想将文件压缩foobartar 存档中archive.tar,但我希望它们在存档中显示为目录bazdir.因此,当我解压某个地方时,我希望在其中bazdir被创建并被foo创建bar

我怎样才能做到这一点?

这将与以下内容相反:

https://stackoverflow.com/questions/939982/how-do-i-tar-a-directory-of-files-and-folders-without-include-the-directory-it
或者
创建平面 tar 存档:添加文件夹时忽略所有父级

答案1

您可以使用该--transform选项。例如:

touch foo bar
tar cf archive.tar foo bar --transform 's,^,bazdir/,'
tar tvf archive.tar 
-rw-r--r-- tigger/tigger     0 2017-10-11 19:32 bazdir/foo
-rw-r--r-- tigger/tigger     0 2017-10-11 19:32 bazdir/bar

有关更多详细信息和更复杂的选项,请参阅如何使用 tar 创建公共基本文件夹以及如何重命名文件夹?- 在姊妹网站上,询问 ubuntu。

答案2

如果您使用的是 macOS,请使用 option-s而不是--transform.

-s 模式

根据模式修改文件或存档成员名称。该模式的格式为 /old/new/[ghHprRsS],其中 old 是基本正则表达式,new 是匹配部分的替换字符串,可选的尾随字母修改处理替换的方式。如果 old 不匹配,则跳过该模式。在 new 中,~ 被替换为匹配项...

可选的尾随 p 指定在成功替换后,应将原始路径名和新路径名打印到标准错误。

根据以上信息,我们可以定义选项-s,如下所示:

$ tar -c -a -v -s "|.*|prefix/~|p" -f ../out.tar.gz 1.txt 2.txt N.txt

1.txt >> prefix/1.txt
a prefix/1.txt
2.txt >> prefix/2.txt
a prefix/2.txt

在哪里

  • |- 是模式部分分隔符,而不是默认的“/”。
  • .*- 是一个正则表达式,用于定义模式的“旧”部分(匹配所有内容)。
  • prefix/~- 是添加到“old”部分之前的表达式(定义为“~”)
  • p- 是一个模式选项,用于打印要存档的文件的原始名称和新名称。

真实世界示例 - 归档 git 存储库中的所有文件(包括子模块):

$ git ls-files --recurse-submodules | tar -c -a -v --files-from - -s "|.*|1.0.2/~|" --file "dist_1.0.2.tar.gz"

a 1.0.2/.gitignore
a 1.0.2/.gitmodules
a 1.0.2/.prettierignore
a 1.0.2/.prettierrc
a 1.0.2/.vscode/settings.json
a 1.0.2/Gulpfile.mjs
a 1.0.2/Ports.mjs
a 1.0.2/Readme.md
a 1.0.2/Version.cjs
a 1.0.2/app.mjs
a 1.0.2/app.test.mjs
a 1.0.2/jest-fastify-env.mjs
a 1.0.2/jest.babel.config.cjs
a 1.0.2/jest.config.mjs
a 1.0.2/jest.setup.mjs
a 1.0.2/lib/conf/Stack.mjs
a 1.0.2/lib/shared/.gitignore
a 1.0.2/lib/shared/AWSS3Client.cjs
a 1.0.2/lib/shared/Api.cjs
a 1.0.2/lib/shared/Api.test.mjs
a 1.0.2/lib/shared/AppConfig.cjs
a 1.0.2/lib/shared/DBApi.cjs
a 1.0.2/lib/shared/DBClient.cjs
a 1.0.2/lib/shared/DBExporter.mjs
a 1.0.2/lib/shared/DynamoDBClient.cjs
a 1.0.2/lib/shared/DynamoDBConnection.cjs
a 1.0.2/lib/shared/RDS.mjs
a 1.0.2/lib/shared/RDSClient.mjs
a 1.0.2/lib/shared/SecuredApi.cjs
a 1.0.2/lib/shared/SecuredApi.test.mjs
a 1.0.2/lib/shared/SecuredApiErrorIds.cjs
a 1.0.2/lib/shared/SharedEnv.cjs
a 1.0.2/lib/shared/conf/AppEnv.cjs
a 1.0.2/lib/shared/helpers/CognitoTokenDownloader.cjs
a 1.0.2/lib/shared/helpers/CognitoTokenDownloader.test.mjs
a 1.0.2/lib/shared/helpers/HTTPAuthHelper.cjs
a 1.0.2/lib/shared/helpers/HTTPAuthHelper.test.mjs
a 1.0.2/lib/shared/helpers/Preprocessor.cjs
a 1.0.2/lib/shared/helpers/Preprocessor.test.mjs
a 1.0.2/lib/shared/helpers/TokenVerifier.cjs
a 1.0.2/lib/shared/helpers/TokenVerifier.test.mjs
a 1.0.2/lib/shared/helpers/TokenVerifierErrorIds.cjs
a 1.0.2/lib/shared/helpers/TypeChecking.cjs
a 1.0.2/lib/shared/helpers/TypeChecking.test.mjs
a 1.0.2/lib/shared/testability/TokenFixture.cjs
a 1.0.2/lib/shared/types/CustomDateFormatter.cjs
a 1.0.2/lib/shared/types/CustomDateFormatter.test.mjs
a 1.0.2/lib/shared/types/EnvName.cjs
a 1.0.2/lib/shared/types/GenericError.cjs
a 1.0.2/package.json
a 1.0.2/scripts/shared/.gitignore
a 1.0.2/scripts/shared/Prompt.cjs
a 1.0.2/scripts/shared/VersionTool.mjs
a 1.0.2/server.mjs
a 1.0.2/yarn.lock

如果您在 macOS 上双击 Finder.app 中的“dist_1.0.2.tar.gz”,您将看到名为“1.0.2”的文件夹,其中包含所有存档文件。

答案3

假设bazdir当前目录中尚不存在,想到的最直接的方法是:

$ ln -s . bazdir
$ tar cvf myfile.tar bazdir/{foo,bar}
a bazdir/foo
a bazdir/bar

.tar创建文件后,我们删除bazdir符号链接:

$ rm bazdir

.tar文件现在包含目录前缀bazdir/

$ tar tvf myfile.tar 
-rw-------  0 jim    wheel       0 Dec 11 13:41 bazdir/foo
-rw-------  0 jim    wheel       0 Dec 11 13:41 bazdir/bar

当我们提取 tar 文件时,bazdir会创建一个真正的目录:

$ tar xvf myfile.tar 
x bazdir/foo
x bazdir/bar
$ find .
.
./myfile.tar
./foo
./bazdir
./bazdir/bar
./bazdir/foo
./bar
$ file bazdir
bazdir: directory

如果您不想触及源目录(或者实际上它是只读的),则可以将符号链接放在其他位置:

$ ln -s $(pwd) /tmp/bazdir
$ tar cvf /tmp/myfile.tar -C /tmp bazdir/{foo,bar}
a bazdir/foo
a bazdir/bar
$ rm /tmp/bazdir
$ tar tvf /tmp/myfile.tar 
-rw-------  0 jim    wheel       0 Dec 11 13:41 bazdir/foo
-rw-------  0 jim    wheel       0 Dec 11 13:41 bazdir/bar

答案4

不是很有效,但明确的方法是将rsync文件保存到某个临时目录,然后保存tar它们。

--transform在许多情况下这是一个很好的功能,但它提供了稍微不同的存档结构,当解包端超出我们的控制时,这可能会破坏解包端。

相关内容