仅限tar文件,没有目录


16

我可能可以编写一个Shell脚本以仅查找文件,然后将列表传递给tar,但是我想知道tar中是否已经有一个内置功能可以在一个命令行中执行此操作?

例如,我找到了--no-recursion开关,但是当我这样做时:

tar --no-recursion -cvf mydir.tar mydir

它仅存档目录中条目的名称(包括子目录!),但不存档任何文件。

我也尝试过:

 tar --no-recursion -cvf mydir.tar mydir/*

但是,尽管它仅归档文件,但它也归档子目录的名称

有没有办法只告诉tar文件而不告诉目录?


5
只是要澄清一下:您是否要创建具有“扁平”结构的存档(即,所有文件混合在一个目录中)?
rozcietrzewiacz

1
您可以创建一个新目录find mydir -type f |xargs cp -t tempdir,然后创建tar tempdir。
凯文

@rozcietrzewiacz是的,是平面的,但仅来自该目录,而不来自子目录。
ateiob 2011年

1
好吧,我想我明白了您要做什么。怎么样find mydir -depth 1 -type f | xargs tar cf mydir.tar
凯文

2
啊,空格。使用find的-exec代替:find mydir -maxdepth 1 -type f -exec tar cvf mydir.tar {} +。在+将所有喜欢xargs的同一命令行上的文件。
凯文

Answers:


11

正如camh所指出的那样,前一个命令有一个小问题,即文件名太多,它将执行一次以上,而随后的调用会以静默方式清除以前的运行。由于我们也不压缩,因此可以追加而不是覆盖:

find mydir -maxdepth 1 -type f -print0 | xargs -0 tar Avf mydir.tar
find mydir -maxdepth 1 -type f -exec tar Avf mydir.tar {} +

Iocnarz的答案使用tar--null-T选择的作品也是如此。如果已cpio安装,使用camh的答案也可以。而且,如果您zsh不介意将其用于命令,那么Gilles 使用zsh glob(*(.)的答案似乎是最简单的。


关键是-maxdepth选项。最终答案,适当处理空格:

find mydir -maxdepth 1 -type f -print0 | xargs -0 tar cvf mydir.tar

这也应该起作用:

find mydir -maxdepth 1 -type f -exec tar cvf mydir.tar {} +

4
两者都可能导致的多个调用tar。二者xargs以及find+变体均具有可传递给tar的最大参数数量。这将导致tar的第二次调用覆盖第一个的输出。
camh 2012年

2
在xargs限制上扩展,xargs默认为最大128KiB命令行。如果文件列表较大,则会第二次(或更多次)调用命令(tar),从而导致静默数据丢失。您可以-x用来强制xargs失败而不是丢失数据,尽管它比静默的数据丢失错误更好,但它仍然不是理想的选择。这种排序错误非常危险,因为起初一切似乎都很好,但是随着文件列表的增长,您将开始触发它,并且可能在尝试还原备份之前不会注意到。那为时已晚。
camh 2012年

@camh你是对的,谢谢你指出这一点;我已经更新以反映这一点。
凯文

1
“最终答案”不正确,如果使用不带-T的“ tar c”,则可能会得到部分结果。
eckes

14

当您要使用findwith时tar,最好的方法是使用cpio代替tarcpio可以编写tar归档文件,并且可以从stdin获取要归档的文件列表。

find mydir -maxdepth 1 -type f -print0 | cpio -o -H ustar -0 > mydir.tar

使用findcpio是一种更统一的方法,因为您find可以利用文件的所有功能进行文件选择,然后cpio进行存档。值得学习这种简单的用法cpio,因为您会发现解决尝试时遇到的麻烦很容易tar


辉煌!我在远古时代就使用过cpio,但从未知道ustar选项。
伊恩·麦克高恩

2
这对我来说比接受的答案要好得多。
戴尔·安德森

1
只是尼特。-maxdepth 1应该在-type f之前,否则您会从一些发现中得到警告
kdubs

谢谢@kdubs。我已将答案更新到-maxdepth之前-type
卡姆

3

我不确定我是否理解您的要求。如果要将常规文件存储在mydir而不是子目录存储,最简单的方法是使用zsh,其中仅匹配常规文件是使用. glob限定符的简单问题:

tar cf mydir.tar mydir/*(.)

3

您甚至可以使用 find ... -print0tar ... --null直接不使用xargs在所有。

find . -maxdepth 1 -type f -print0 | tar cvf mydir.tar --null -T -

在给定的示例中, --no-recursion to选项tar不是必需的,因为仅文件路径(而不是目录路径)将从传递findtar

但是,在以下示例中,使用--no-recursion选项to tar可以防止tar对目录进行双重归档。find将执行目录树递归,而不是执行递归tar

# compare
find . -print0 | tar cf mydir.tar --null -T -
tar -tf mydir.tar | nl

find . -print0 | tar cf mydir.tar --null --no-recursion -T -
tar -tf mydir.tar | nl

2

正如引言部分所述man tar(最后一句话),

使用目录名总是意味着以下子目录应包含在归档中。

我理解为您问题的“否”答案。


良好的渔获,除了焦油现在包括许多排斥meachisms(例如--no-recursion--exclude-tag等)。我正在研究 --exclude-tag哪些看起来很有希望,但似乎与我正在寻找的恰好相反。
ateiob 2011年

我尝试了此操作,发现字符已从长路径名中删除。建议将tar与-T和--null一起使用可避免此问题。
Paul Brannan

1
star -c -C startdir -find . ! -type d > out.tar

省略-C startdir并替换.startdir如果它应该出现在存档中,则为。

这是基于libfind功能的最有效的方法。Libfind还提供了可-chown -chgrp -chmod在适当位置修改struct stat并允许存档不同元数据的基元。这也适用于列表和提取模式,并且在许多情况下无需提取整个档案。


您可以-find-copy模式下使用。该名男子页大纲建议你可以,但我没有能够使它发挥作用(同时试图回答如何同时保持文件夹结构复制修改的文件)(与席利- 2016年2月10日)
斯特凡Chazelas

我没有测试更长的时间了。可能是当前存在错误。手册页说最后一个参数将是提取目录,但是当我尝试这样做时,我得到:“提取模式尚不支持路径参数”。这是您尝试时得到的吗?
2016年

是。该名男子页也说,你只能有后-find找到论据,但如果我把目标目录之前-find我也得到一个错误
斯特凡Chazelas

在提取过程中,有一些代码可以关闭查找代码,并且错误消息来自期望-c但也应允许-copy的不正确检查。在-copy模式下,查找解析器不应包含最后一个参数。
2016年

1
现在,最终解决方案已在schily工具中发布,网址为sourceforge.net/projects/schilytools/files/schily-2016-03-11.tar.bz2,这也解决了star中缺少setlocale()的问题,这使得- C指令star -find
schily

0

我可能已经找到了解决方案。

find mydir -type f -printf '%P\0'|tar czvf mydir.tar.gz -C mydir --null -T -

这可能会花费一些钱,但是无论如何它都会起作用,因为这不依赖于xargs。


-1

dir = your_dir; cd $ dir; tar -cvf file.tar`find。-maxdepth 1 -type f -print`

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.