Linux tar 一个目录,但不要在存档中存储完整的绝对路径

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/18681595/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-07 00:46:23  来源:igfitidea点击:

Tar a directory, but don't store full absolute paths in the archive

linuxbashbackuptar

提问by QuentinC

I have the following command in the part of a backup shell script:

我在备份 shell 脚本的一部分中有以下命令:

tar -cjf site1.bz2 /var/www/site1/

When I list the contents of the archive, I get:

当我列出档案的内容时,我得到:

tar -tf site1.bz2
var/www/site1/style.css
var/www/site1/index.html
var/www/site1/page2.html
var/www/site1/page3.html
var/www/site1/images/img1.png
var/www/site1/images/img2.png
var/www/site1/subdir/index.html

But I would like to remove the part /var/www/site1from directory and file names within the archive, in order to simplify extraction and avoid useless constant directory structure. Never know, in case I would extract backuped websites in a place where web data weren't stored under /var/www.

但是我想/var/www/site1从存档中的目录和文件名中删除部分,以简化提取并避免无用的恒定目录结构。永远不知道,以防万一我将备份的网站提取到 Web 数据未存储在/var/www.

For the example above, I would like to have :

对于上面的例子,我想要:

tar -tf site1.bz2
style.css
index.html
page2.html
page3.html
images/img1.png
images/img2.png
subdir/index.html

So, that when I extract, files are extracted in the current directory and I don't need to move extracted files afterwards, and so that sub-directory structures is preserved.

因此,当我提取文件时,文件将提取到当前目录中,之后我不需要移动提取的文件,从而保留子目录结构。

There are already many questions about tar and backuping in stackoverflowand at other places on the web, but most of them ask for dropping the entire sub-directory structure (flattening), or just add or remove the initial / in the names (I don't know what it changes exactly when extracting), but no more.

已经有很多关于 tar 和备份在网络上stackoverflow和其他地方的问题,但他们中的大多数要求删除整个子目录结构(扁平化),或者只是添加或删除名称中的首字母 /(我不t 知道它在提取时究竟发生了什么变化),但仅此而已。

After having read some of the solutions found here and there as well as the manual, I tried :

在阅读了这里和那里的一些解决方案以及手册后,我尝试了:

tar -cjf site1.bz2 -C . /var/www/site1/
tar -cjf site1.bz2 -C / /var/www/site1/
tar -cjf site1.bz2 -C /var/www/site1/ /var/www/site1/
tar -cjf site1.bz2 --strip-components=3 /var/www/site1/

But none of them worked the way I want. Some do nothing, some others don't archive sub-directories anymore.

但是他们都没有按照我想要的方式工作。有些什么都不做,有些则不再存档子目录。

It's inside a backup shell script launched by a Cron, so I don't know well, which user runs it, what is the path and the current directory, so always writing absolute path is required for everything, and would prefer not changing current directory to avoid breaking something further in the script (because it doesn't only backup websites, but also databases, then send all that to FTP etc.)

它在一个 Cron 启动的备份 shell 脚本中,所以我不太清楚,哪个用户运行它,路径和当前目录是什么,所以总是写绝对路径是所有东西的必需品,并且宁愿不改变当前目录避免在脚本中进一步破坏某些内容(因为它不仅备份网站,还备份数据库,然后将所有内容发送到 FTP 等)

How to achieve this?

如何实现这一目标?

Have I just misunderstood how the option -C works?

我是不是误解了选项 -C 的工作原理?

采纳答案by Lars Brinkhoff

tar -cjf site1.tar.bz2 -C /var/www/site1 .

In the above example, tar will change to directory /var/www/site1before doing its thing because the option -C /var/www/site1was given.

在上面的示例中,tar 将/var/www/site1在执行其操作之前更改为目录,因为-C /var/www/site1已给出选项。

From man tar:

来自man tar

OTHER OPTIONS

  -C, --directory DIR
       change to directory DIR

回答by Grizli

The option -Cworks; just for clarification I'll post 2 examples:

该选项-C有效;为了澄清起见,我将发布 2 个示例:

  1. creation of a tarball without the full path: full path /home/testuser/workspace/project/application.warand what we want is just project/application.warso:

    tar -cvf output_filename.tar  -C /home/testuser/workspace project
    

    Note: there is a space between workspaceand project; tar will replace full path with just project.

  2. extraction of tarball with changing the target path (default to ., i.e current directory)

    tar -xvf output_filename.tar -C /home/deploy/
    

    tarwill extract tarball based on given path and preserving the creation path; in our example the file application.warwill be extracted to /home/deploy/project/application.war.

    /home/deploy: given on extract
    project: given on creation of tarball

  1. 创建没有完整路径的 tarball:完整路径/home/testuser/workspace/project/application.war,我们想要的就是project/application.war这样:

    tar -cvf output_filename.tar  -C /home/testuser/workspace project
    

    注意:workspace和之间有一个空格project;tar 将仅用 .tar 替换完整路径project

  2. 通过更改目标路径提取 tarball(默认为.,即当前目录)

    tar -xvf output_filename.tar -C /home/deploy/
    

    tar将根据给定的路径提取 tarball 并保留创建路径;在我们的示例中,文件application.war将被提取到/home/deploy/project/application.war.

    /home/deploy: 在提取时
    project给出 : 在创建 tarball 时给出

Note : if you want to place the created tarball in a target directory, you just add the target path before tarball name. e.g.:

注意:如果要将创建的 tarball 放在目标目录中,只需在 tarball 名称之前添加目标路径即可。例如:

tar -cvf /path/to/place/output_filename.tar  -C /home/testuser/workspace project

回答by Chinthaka Senanayaka

Seems -Coption upto tar v2.8.3 does not work consistently on all the platforms (OSes). -Coption is said to add directory to the archive but on Mac and Ubuntu it adds absolute path prefix inside generated tar.gz file.

似乎-Ctar v2.8.3 的选项在所有平台 (OS) 上都不能一致地工作。-C据说将目录添加到存档中,但在 Mac 和 Ubuntu 上,它在生成的 tar.gz 文件中添加了绝对路径前缀。

tar target_path/file.tar.gz -C source_path/source_dir

Therefore the consistent and robust solution is to cdin to source_path (parent directory of source_dir) and run

因此,一致且健壮的解决方案是进入cdsource_path(source_dir 的父目录)并运行

tar target_path/file.tar.gz source_dir

or

或者

tar -cf target_path/file.tar.gz source_dir

in your script. This will remove absolute path prefix in your generated tar.gz file's directory structure.

在你的脚本中。这将删除生成的 tar.gz 文件目录结构中的绝对路径前缀。

回答by WLatif

The following command will create a root directory "." and put all the files from the specified directory into it.

以下命令将创建一个根目录“.”。并将指定目录中的所有文件放入其中。

tar -cjf site1.tar.bz2 -C /var/www/site1 .

If you want to put all files in root of the tar file, @chinthaka is right. Just cd in to the directory and do:

如果要将所有文件放在 tar 文件的根目录中,@chinthaka 是正确的。只需 cd 进入目录并执行:

tar -cjf target_path/file.tar.gz *

This will put all the files in the cwd to the tar file as root files.

这会将 cwd 中的所有文件作为根文件放入 tar 文件中。

回答by Sergey Asachev

Using the "point" leads to the creation of a folder named "point" (on Ubuntu 16).

使用“point”会导致创建一个名为“point”的文件夹(在 Ubuntu 16 上)。

tar -tf site1.bz2 -C /var/www/site1/ .

I dealt with this in more detail and prepared an example. Multi-line recording, plus an exception.

我更详细地处理了这个问题并准备了一个例子。多行录音,外加一个例外。

tar -tf site1.bz2\
    -C /var/www/site1/ style.css\
    -C /var/www/site1/ index.html\
    -C /var/www/site1/ page2.html\
    -C /var/www/site1/ page3.html\
    --exclude=images/*.zip\
    -C /var/www/site1/ images/
    -C /var/www/site1/ subdir/
/

回答by Hirurg103

If you want to archive a subdirectory and trim subdirectory path this command will be useful:

如果要存档子目录并修剪子目录路径,此命令将很有用:

tar -cjf site1.bz2 -C /var/www/ site1