如何将 'tar' 命令与 'find' 结合使用

如何将 'tar' 命令与 'find' 结合使用

find 命令给出以下输出:

[root@localhost /]# 查找 var/log/-iname anaconda.*
var/log/anaconda.log
var/log/anaconda.xlog
var/log/anaconda.yum.log
var/log/anaconda.syslog
var/log/anaconda.program.log
var/log/anaconda.storage.log

与 tar 结合后显示以下输出:

[root@localhost /]# find var/log/-iname anaconda.*-exec tar-cvf file.tar {} \;
var/log/anaconda.log
var/log/anaconda.xlog
var/log/anaconda.yum.log
var/log/anaconda.syslog
var/log/anaconda.program.log
var/log/anaconda.storage.log

但在列出 tar 文件时,它只显示一个文件

[root@localhost /]# tar -tvf 文件.tar
-rw------- root/root 208454 2012-02-27 12:01 var/log/anaconda.storage.log

我在这里做错了什么?

使用 xargs 我得到了这个输出:

[root@localhost /]# 查找 var/log/-iname anaconda.* | xargs tar -cvf file1.tar

第二个问题

打字时/在 var 前面,表示find /var/log为什么它会给出这个消息tar:从成员名称中删除前导“/”

[root@localhost /]# find /var/log/-iname anaconda.*-exec tar -cvf file.tar {} \;
tar:从成员名称中删除前导“/”
/var/log/anaconda.log
tar:从成员名称中删除前导“/”
/var/log/anaconda.xlog
tar:从成员名称中删除前导“/”
/var/log/anaconda.yum.log
tar:从成员名称中删除前导“/”
/var/log/anaconda.syslog
tar:从成员名称中删除前导“/”
/var/log/anaconda.program.log
tar:从成员名称中删除前导“/”
/var/log/anaconda.storage.log

简单来说,以下两者有何区别?

find var/logfind /var/log

答案1

笔记:@Iain 的回答寻找更有效的解决方案。

请注意,find将调用以下-exec操作每一个文件它发现了。

如果您tar -cvf file.tar {}对每个文件find输出都运行,这意味着您每次都会覆盖file.tar,这也解释了为什么您最终只剩下一个包含最后anaconda.storage.log一个文件find输出的档案。

现在你真的想附加将文件放入存档中,而不是每次都创建它(这是该-c选项的作用)。因此,请使用以下命令:

find var/log/ -iname "anaconda.*" -exec tar -rvf file.tar {} \;

-r选项将附加到档案中,而不是每次都重新创建它。

笔记:替换-iname anaconda.*-iname "anaconda.*"。星号是通配符,可以扩展在 shellfind看到它之前,它就已经被删除了。为了防止这种扩展,请将参数括在双引号中。


至于tar删除前导/:档案应该只包含相对的文件名。如果您添加以 开头的文件/,则它们将存储为绝对/var/…例如,文件名,其字面意思就是您的计算机上的文件名。

IIRC 这只是对 GNU 以外的实现的一种预防措施,这样更安全,因为如果档案包含相对文件名,则在提取档案tar时不会覆盖实际数据。/var/…

答案2

您可以使用类似如下的方法:

find var/log -iname 'anaconda.*' -print0 | tar -cvf somefile.tar --null -T -

-print0一起-T作用允许文件名带有空格、换行符等等。最后-告诉 tar 从 stdin 读取输入文件名。

请注意,-print0必须位于声明的末尾,这个答案。否则,您可能会获得比预期更多的文件。

答案3

尝试这个:

tar -cvf file.tar `find var/log/ -iname "anaconda.*"`

您尝试使用find-exec tar但该选项的工作方式是-exec,它会对找到的每个匹配文件运行一次该命令,从而导致tar每次都覆盖它生成的 tar 文件。这就是为什么您只得到最后一个。此外,您需要将您指定的模式放在引号中,find以便 shell 在将其传递给 之前不会对其进行扩展find

使用带有反引号的命令替换(或者$(...)如果您愿意,可以使用符号),将生成的整个名称列表find作为参数粘贴回命令行tar,使其一次将它们全部写入。

答案4

有两种方法-exec可以工作。一种方法是多次运行该命令 - 每个文件一次;另一种方法运行该命令一次,将所有文件作为参数列表。

  • -exec tar -cvf file.tar {} ';'对每个文件运行tar命令,每次都覆盖存档。
  • -exec tar -cvf file.tar {} '+'运行tar一次命令,创建所有找到的文件的存档。

相关内容