创建具有原始文件结构的存档文件,以便解压文件时将这些文件/文件夹提取到原来的位置

创建具有原始文件结构的存档文件,以便解压文件时将这些文件/文件夹提取到原来的位置

假设我有一个如下文件结构:

/
 file0.txt
 file00.txt
 --folderA
    fileA1.txt
    fileA2.txt
 --folderB
    fileB.dat
    fileB.txt
    noisefile.noise123
   --folderBB
      fileBB1.dat
      fileBB2.dat
      fileBB.txt
      noisefile.noise6hy

/并使用以下命令创建一个 zip 文件(来自):

zip -r archive.zip /*.txt /folderA/*.txt /folderB -x /folderB/noisefile.\*

此命令不保留原始文件结构,当我解压它时,它不会解压到原来的位置。有没有办法实现这一点,无论是否使用(其他可用工具)zip

类似的类比是包含所有结构的.deb文件,安装时将其提取到原始位置。我不使用文件的原因是它将安装(注册?)在系统上,而我想要做的只是备份和恢复文件。也许可以做我想做的事,但我不知道?data.tar.gzdebdeb

答案1

一般方式

每个存储相对路径并提取当前工作目录中文件的归档器都可以“强制”执行您想要的操作。您需要

  • /像问题中那样从根目录()创建一个档案(提供绝对路径可能就足够了,即使您在另一个目录中);
  • 从根目录提取档案。

所以cd /(或pushd /)至关重要。

这尤其适用于zip。我将您的问题视为简化流程、摆脱 的请求cd /。能够相对于真实工作目录解释目标文件(在问题中)的能力archive.zip也很好;显然是在cd / archive.zip之后/archive.zip


tar

所需的功能在 中可用tar。在 Linux 中,tar是一个常见的归档器,尽管 POSIX 并不要求如此(POSIX 归档器是pax)。

使用tar,它的--absolute-names/-P选项对于您的情况很有用。手册状态:

--absolute-names
-P

通常在创建档案时,会从成员名称中tar删除首字母/,而从档案中提取时,tar如果名称具有首字母/或内部字母,则会对其进行特殊处理..。此选项可禁用该行为。请参阅章节绝对文件名

要实现你想要的目标,有几个条件:

  • 创建存档时,您需要提供要存档的文件的绝对路径。在您的示例中,/*.txt /folderA/*.txt /folderB扩展为绝对路径。请注意,shell 会扩展未加引号的*; 然后tar(或zip在示例中)接收扩展的路径。
  • 创建档案时,您需要使用-P(或--absolute-names)。如果不使用 ,tar则将存储每个路径而不使用前导/(您仍然可以在 中提取文件/,这正是上面介绍的通用方法)。
  • 提取时,您需要-P再次使用。如果不这样做,无论如何tar都会从每个路径中删除前导/,并且您将重新创建存储的目录树作为当前工作目录的子树。请注意,您仍然需要在提取时明确请求所需的行为,调整后的压缩命令是不够的。请参阅下一段以了解为什么这是一件好事。

相较于一般方式的优点:

  • 可以将要创建的档案(例如archive.tar)指定为相对于真实工作目录的路径。
  • 您可以将某些路径(要存档的文件)指定为相对路径,将其他路径指定为绝对路径。问题是关于所有绝对路径,但一般来说,您可能希望混合使用它们。

补充笔记:

  • zip充当归档器和压缩器。这不太像 Unix(参见“专心做好一件事”)。如果要使用 进行压缩tar,请压缩生成的存档或告诉tar压缩在创作过程中即时进行。
  • 在示例中,您-r启用了递归。tar这是默认行为
  • 在示例中,您曾-x排除一些文件。使用tar它将类似于--exclude=/folderB/noisefile.\*--exclude='noisefile.*'(此命令还将排除 中的一个文件folderBB)。阅读

例子:

# archiving
tar -cPzf archive.tgz --exclude='noisefile.*' /*.txt /folderA/*.txt /folderB

# extracting
tar -xPf archive.tgz

为什么默认不提取绝对路径?

默认行为是提取相对于当前工作目录的每个路径,这是一件好事。这样,即使您是 root 用户,也不必担心某些存档(您希望只提取当前工作目录中的文件)是否是恶意的,并在其他地方提取文件(例如,它可能会覆盖/etc/passwd或诸如此类)。您可以通过以下方式允许这种潜在的危险行为:有意而明确地选择它(事先cd /或使用非默认选项tar -P)。


如果我真的想要默认使用绝对路径吗?

此别名

alias tar='tar -P'   # but think twice

将在交互式 shell 中的每个调用中注入相关选项tar。或者,可以使用包装器函数或包装器脚本来注入选项。即使从另一个脚本调用,包装器脚本也可以轻松工作(相比之下:通常别名在脚本中不起作用)。

通用方法也可以作为给定归档器的脚本来实现,尽管最基本的方法(在/调用实际归档器之前仅将目录更改为)将导致相对于 进行解释的相对路径/,而不管当前工作目录如何。这可以通过适当的命令行解析和内部逻辑来修复;但通常这不是一项简单的任务。

反正我不建议改变默认行为。上一段解释了原因。如果我是你,我会接受提取时需要非默认操作;我会执行它们有意地无论何时。


提示

常规方法是将您置于根目录中。您可能希望cd返回到您的真实工作目录。有用的技巧:

  • cd -相当于cd "$OLDPWD" && pwd。这是返回的基本方法cd

  • pushd /cd /而不是popd在末尾输入 ,。我知道输入cd /and会更快cd -,但如果您在日常工作中习惯了pushd+,popd那么您可能会在这种情况下自然而然地使用它们,而不会再三考虑,也不会破坏您的习惯。

  • 子 shell,例如(cd / && unzip …)。这不会更改主 shell 中的当前工作目录。由于变量在整个子 shell 执行之前展开,因此这个技巧特别有用;这意味着您可以使用 来$PWD传递您的真实工作目录:

      (cd / && unzip "$PWD"/archive.zip)
    

相关内容