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

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

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

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

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

但是我想从存档中的目录和文件名中删除/var/www/site1部分,以简化提取和避免无用的常量目录结构。永远不知道,万一我将提取备份的网站在一个地方,网站数据不存储在/var/www下。

对于上面的例子,我希望有:

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

当我提取的时候,文件是在当前目录下提取的之后我不需要移动提取的文件,所以子目录结构是保留的。

stackoverflow和web上的其他地方已经有很多关于tar和备份的问题,但大多数问题都要求删除整个子目录结构(扁平化),或者只是在名称中添加或删除首字母/(我不知道提取时它到底改变了什么),但没有更多。

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

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/

但没有一个是我想要的。有些不做任何事,有些不再归档子目录。

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

如何做到这一点?

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

297121 次浏览
tar -cjf site1.tar.bz2 -C /var/www/site1 .

在上面的例子中,tar会在做它的事情之前改变到目录/var/www/site1,因为选项-C /var/www/site1是给定的。

man tar:

OTHER OPTIONS


-C, --directory DIR
change to directory DIR

选项-C起作用;为了澄清,我举两个例子:

  1. 创建一个没有完整路径的tarball: 完整路径/home/testuser/workspace/project/application.war,我们想要的只是project/application.war,因此:

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

    注:workspaceproject之间有一个空格;

    . tar将用project替换完整路径
  2. 改变目标路径(默认为.,即当前目录)

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

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

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

  3. 时给出

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

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

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

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

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

tar target_path/file.tar.gz source_dir

tar -cf target_path/file.tar.gz source_dir

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

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

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

如果你想把所有文件放在tar文件的根目录下,@chinthaka是正确的。只需cd到目录,并做:

tar -cjf target_path/file.tar.gz *

这将把cwd中的所有文件作为根文件放到tar文件中。

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

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

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

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/
/

如果你想归档子目录并修剪子目录路径,这个命令将是有用的:

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

发现tar -cvf site1-$seqNumber.tar -C /var/www/ site1是比tar -cvf site1-$seqNumber.tar -C /var/www/site1 . 更友好的解决方案(注意第二个解决方案中的< >。< / >强),原因如下

  • Tar文件名可以不重要,因为原来的文件夹现在是一个存档条目
  • Tar文件名对内容无关紧要,现在可以用于其他目的,如序列号,定期备份等。

一个小细节:

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

将文件添加为

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

如果你真的想要

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

你也应该

  • 先将CD放入目录
  • 或运行
tar -cjf site1.tar.bz2 -C /var/www/site1 $(ls -A /var/www/site1)

注意,它不支持空格。谢谢@dragon788和@Fonic。