更有效的方法来查找和tar数百万个文件

Stu*_*son 22 bash tar find

我在命令行提示符下运行了两天的作业:

find data/ -name filepattern-*2009* -exec tar uf 2009.tar {} ;
Run Code Online (Sandbox Code Playgroud)

它需要永远,然后一些.是的,目标目录中有数百万个文件.(每个文件在一个良好的散列目录结构中只有8个字节.)但是只是运行...

find data/ -name filepattern-*2009* -print > filesOfInterest.txt
Run Code Online (Sandbox Code Playgroud)

......只需要两个小时左右.按照我的工作速度,它将在几周内完成.这似乎是不合理的.这样做有效吗? 也许使用更复杂的bash脚本?

第二个问题是"为什么我目前的做法如此缓慢?"

小智 25

一种选择是使用cpio生成tar格式的存档:

$ find data/ -name "filepattern-*2009*" | cpio -ov --format=ustar > 2009.tar
Run Code Online (Sandbox Code Playgroud)

cpio本身使用来自stdin的文件名列表,而不是顶级目录,这使它成为这种情况的理想工具.

  • `find data/-print0 | tar -T - --null --create -f archive.tar`从stdout读取文件列表,并使用null文件分隔符 (5认同)
  • 我的ubuntu tar不喜欢在`-T`之后使用`--null`.我不得不使用:`find data/-print0 | tar --null -T - --create -f archive.tar` (3认同)
  • 这是一个优雅的解决方案.你可以通过网络运行它.用`|替换`> 2009.tar` ssh主机tar xf -` (2认同)

fra*_*nkc 20

如果您已经执行了创建文件列表的第二个命令,只需使用该-T选项告诉tar从该保存的文件列表中读取文件名.运行1 tar命令vs N tar命令会好很多.

  • 在这种情况下要小心`xargs`:如果有多个文件名传递给它,它会在文件列表的子集上多次执行`tar`.在你的情况下,使用`tar -u`可能有效,但是如果你正在创建一个tar文件`tar -c`,那么只有文件的最后一个子集将在那里完成... (2认同)

小智 8

这是一个find-tar组合,可以在不使用xargs或exec的情况下做你想做的事情(这会导致显着的加速):

tar --version    # tar (GNU tar) 1.14 

# FreeBSD find (on Mac OS X)
find -x data -name "filepattern-*2009*" -print0 | tar --null --no-recursion -uf 2009.tar --files-from -

# for GNU find use -xdev instead of -x
gfind data -xdev -name "filepattern-*2009*" -print0 | tar --null --no-recursion -uf 2009.tar --files-from -

# added: set permissions via tar
find -x data -name "filepattern-*2009*" -print0 | \
    tar --null --no-recursion --owner=... --group=... --mode=... -uf 2009.tar --files-from -
Run Code Online (Sandbox Code Playgroud)


Mic*_*hař 7

这有xargs:

find data/ -name filepattern-*2009* -print0 | xargs -0 tar uf 2009.tar
Run Code Online (Sandbox Code Playgroud)

由于没有太多信息,因此很难猜测为什么它很慢.目录的结构是什么,您使用什么文件系统,如何在创建时配置它.对于大多数文件系统来说,在单个目录中拥有数百万个文件是非常困难的.

  • @Stu嘿,它又是我:)你可以简单地用原来的命令替换```和`+`来获得完全相同的效果.只需在-exec上查看相应的手册页条目即可 (3认同)