代码之家  ›  专栏  ›  技术社区  ›  Stu Thompson Helter Scelter

查找数百万文件的更有效方法

  •  21
  • Stu Thompson Helter Scelter  · 技术社区  · 16 年前

    find data/ -name filepattern-*2009* -exec tar uf 2009.tar {} ;
    

    这需要时间 永远 ,然后是一些。是的,目标目录中有数百万个文件(在散列良好的目录结构中,每个文件只有区区8个字节)。。。

    find data/ -name filepattern-*2009* -print > filesOfInterest.txt
    

    周 .. 这似乎不合理。 有没有更有效的方法? 也许用更复杂的bash脚本?

    第二个问题是

    8 回复  |  直到 16 年前
        1
  •  20
  •   Stu Thompson Helter Scelter    16 年前

    如果已经执行了创建文件列表的第二个命令,只需使用 -T 选项告诉tar从保存的文件列表中读取文件名。运行1tar命令和ntar命令会更好。

        2
  •  25
  •   Matthew Mott    16 年前

    备份文件

    $ find data/ -name "filepattern-*2009*" | cpio -ov --format=ustar > 2009.tar
    

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

        3
  •  8
  •   bashfu    16 年前

    下面是一个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 -
    
        4
  •  7
  •   Michal Čihař    16 年前

    有以下xargs:

    find data/ -name filepattern-*2009* -print0 | xargs -0 tar uf 2009.tar
    

        5
  •  3
  •   bashfu    16 年前

    要正确处理带有奇怪(但合法)字符(如换行符,…)的文件名,应使用find的-print0将文件列表写入filesOfInterest.txt:

    find -x data -name "filepattern-*2009*" -print0 > filesOfInterest.txt
    tar --null --no-recursion -uf 2009.tar --files-from filesOfInterest.txt 
    
        6
  •  2
  •   Michael Aaron Safyan    16 年前

        7
  •  1
  •   ruffrey    7 年前

    有一个实用程序叫做 tarsplitter

    tarsplitter -m archive -i folder/*.json -o archive.tar -p 8
    

    将使用8个线程将匹配“folder/*.json”的文件归档到“archive.tar”的输出归档中

    https://github.com/AQUAOSOTech/tarsplitter

        8
  •  1
  •   Ryan Rudes    6 年前

    在使用Python的tarfile库找到一个更简单、可能更快的解决方案之前,我在linux上苦苦挣扎了很长一段时间。

    1. 使用glob.glob搜索所需的文件路径
    2. 将每个文件路径添加到此存档
    3. 关闭存档

    import tarfile
    import glob
    from tqdm import tqdm
    
    filepaths = glob.glob("Images/7 *.jpeg")
    n = len(filepaths)
    print ("{} files found.".format(n))
    print ("Creating Archive...")
    out = tarfile.open("Images.tar.gz", mode = "a")
    for filepath in tqdm(filepaths, "Appending files to the archive..."):
      try:
        out.add(filepath)
      except:
        print ("Failed to add: {}".format(filepath))
    
    print ("Closing the archive...")
    out.close()
    

    找到16222个文件路径并创建存档总共花费了大约12秒,但是,这主要是通过简单地搜索文件路径来完成的。创建包含16000个文件路径的tar存档只花了7秒钟。使用一些多线程,这可能会快得多。

    如果您正在寻找多线程实现,我已经制作了一个,并将其放在这里:

    import tarfile
    import glob
    from tqdm import tqdm
    import threading
    
    filepaths = glob.glob("Images/7 *.jpeg")
    n = len(filepaths)
    print ("{} files found.".format(n))
    print ("Creating Archive...")
    out = tarfile.open("Images.tar.gz", mode = "a")
    
    def add(filepath):
      try:
        out.add(filepath)
      except:
        print ("Failed to add: {}".format(filepath))
    
    def add_multiple(filepaths):
      for filepath in filepaths:
        add(filepath)
    
    max_threads = 16
    filepaths_per_thread = 16
    
    interval = max_threads * filepaths_per_thread
    
    for i in tqdm(range(0, n, interval), "Appending files to the archive..."):
      threads = [threading.Thread(target = add_multiple, args = (filepaths[j:j + filepaths_per_thread],)) for j in range(i, min([n, i + interval]), filepaths_per_thread)]
      for thread in threads:
        thread.start()
      for thread in threads:
        thread.join()
    
    print ("Closing the archive...")
    out.close()
    

    当然,您需要确保 max_threads filepaths_per_thread 优化设计;创建线程需要时间,因此实际上 做 它已经存在,只需添加到先前存在的存档中,而不是重置它或创建一个新的存档。

        9
  •  -2
  •   Oleg Kuznetsov    13 年前

    find *.1  -exec tar czf '{}.tgz' '{}' --remove-files \;