如何在Shell中管理大量文件?


9

$ ls ./dir_with_huge_amount_of_files/errors/

假设目录中充满了带有unix时间戳的图片,我的意思是用GB甚至更多来衡量很多。诸如此类的Shell命令ls将获得溢出样式的警告,因为它们并非设计用于处理数百万(或更多)图片。如何管理如此大量的文件?例如,如果要在中间找到图片(根据名称和创建时间中的时间戳记),是否有某些文件系统提供内置的搜索功能?您将使用哪些命令?我尝试了舒适lsfind带有必要的标志,但是它们要么很慢,要么生成警告,因此我认为我需要更好的文件系统或db或类似的东西来对图片进行预索引。我基本上需要一个阵列,照片的inode应该按时间顺序放置在该阵列上。怎么做?以后,可以添加带有unix时间戳的元数据。

[更新]

当前答案存在严重缺陷,人们只是在没有经验检验的情况下发布答案排序。如果他们测试了他们的建议,他们可能会失败。因此,我为您创建了一个命令行工具,您可以通过该工具创建沙箱来创建大量文件,并像对1e7数量的文件一样测试您的建议。生成文件可能需要很长时间,因此请耐心等待。如果有人知道更快的方法,请编辑代码。键入python code.py --help以获取帮助。玩得开心!

使用示例创建很多脏文件

$ ls ./data2
ls: ./data2: No such file or directory
$ python testFill.py -n 3 -d 7                                                 
$ tree data2/                                                                  
data2/
|-- 0
|   |-- 1302407302636973
|   |-- 1302407302638022
|   `-- 1302407302638829
|-- 1
|   |-- 1302407302639604
|   |-- 1302407302641652
|   `-- 1302407302642399
|-- 2
|   |-- 1302407302643158
|   |-- 1302407302645223
|   `-- 1302407302646026
|-- 3
|   |-- 1302407302646837
|   |-- 1302407302649110
|   `-- 1302407302649944
|-- 4
|   |-- 1302407302650771
|   |-- 1302407302652921
|   `-- 1302407302653685
|-- 5
|   |-- 1302407302654423
|   |-- 1302407302656352
|   `-- 1302407302656992
`-- 6
    |-- 1302407302657652
    |-- 1302407302659543
    `-- 1302407302660156

7 directories, 21 files

代码testFill.py

# Author: hhh
# License: ISC license

import os, math, time, optparse, sys

def createHugeAmountOfFiles(fileAmount, dirAmount):
   counter = 0
   DENSITY = 1e7
   dir = "./data/"

   do = dir+str(counter)+"/"
   while (os.path.exists(do)):
      counter = counter+1
      do = dir+str(counter)+"/"

   os.mkdir(do)

   for d in range(int(dirAmount)):
      for f in range(int(fileAmount)):
         timeIt = int(time.time()*1e6)
         if (not os.path.exists(do)):
            os.mkdir(do)

         if (timeIt % DENSITY == 0):
            counter = counter+1
            do = dir+str(counter)+"/"

            if (not os.path.exists(do)):
               os.mkdir(do)


         do = dir+str(counter)+"/"
         if(not os.path.exists(do)):
            os.mkdir(do)

         f = open(do+str(timeIt), 'w')
         f.write("Automatically created file to test Huge amount of files.")
         f.close()
      counter = counter +1


def ls(dir):
   for root, dirs, files in os.walk("./data/"+dir):
      print(files)

def rm(dir):
   for root, dirs, files in os.walk("./data/"+dir):
      for f in files:
         os.remove("./data/"+dir+"/"+f)


def parseCli():
   parser = optparse.OptionParser()
   parser.add_option("-f", "--file", dest="filename",
                     help="Location to remove files only in ./Data.", metavar="FILE")
   parser.add_option("-n", "--number", dest="number",
                     help="Number of files to generate", metavar="NUMBER")
   parser.add_option("-r", "--remove", dest="remove",
                     help="Data -dir content to remove", metavar="NUMBER")
   parser.add_option("-d", "--dir", dest="dir",
                     help="Amount of dirs to generate", metavar="NUMBER")
   parser.add_option("-q", "--quiet",
                     action="store_false", dest="verbose", default=True,
                     help="don't print status messages to stdout")

   return parser.parse_args()

def main():
   (options, args) = parseCli()

   if (options.filename):
      ls(options.filename)
   if (options.number and options.dir):
      createHugeAmountOfFiles(options.number, options.dir)
   if (options.remove):
      rm(options.remove)


main()

2
对于如此大规模的数据集,@hhh可能是唯一的适当索引
编排的

@xenoterracide:但是,即使数据库必须使用数组之类的东西来实现快速搜索,数据库听起来也太过强大了。拍照的来源在这里:github.com/fsphil/fswebcam。也许,我可以在保存图片的时间上对其进行一些修改,以便在文件中附加一行带有inode-number&unix-time-stamp的行。现在,不是图片,而是行,搜索图片会更快。甚至更容易地,每次将图片保存到磁盘时,我都会在其时间戳文件中添加一行。全面解决方案。但是不会用当前的图片解决问题,所以相关的问题。

@hhh您正在使用什么文件系统?还是没有关系... ext确实具有一些性能增强功能,这些功能可能默认情况下未启用。尽管即使是那些可能也无法满足您的需求。数据库针对这些问题进行了优化,并具有各种索引解决方案来处理它们。例如btree索引不仅是一个简单的数组...
xenoterracide 2011年

@xenoterracide:ext3,不确定是否重要。我认为我说明的解决方案解决了将来的搜索问题,但是对于当前的照片完全没有帮助,搜索非常耗时。

1
您在一个目录中有数百万个文件吗?如果是这样,您可以考虑根据文件名的第一个字符将它们分成一个或两个级别的深子目录,例如:a/b/abcdef.jpg
alex

Answers:


4

尝试使用其他外壳。我建议例如尝试使用zsh,看看它是否允许更多参数。

如果我理解正确,文件名的一部分就是UNIX时间戳。建议将文件分成文件夹。如果日期/时间格式是UNIX纪元数,则将该数字的小数部分(例如10000)放在单独的文件夹中。

如果ISO 8601时间戳是文件名的一部分,则只需除以年,月或日。


1
ls和find都不是内置在bash或zsh中的,因此目前尚不清楚在这种情况下切换shell会有什么帮助。
罗宾·格林

关于外壳扩展。如果外壳无法扩展球形,则可能是问题所在。
polemon 2011年

我对在大约1e6文件上运行命令进行了几次测试,ZSH面临相同的问题:"$ cp * Test/ ksh: cp: Argument list too long % rm * zsh: sure you want to delete all the files in /home/user/Downloads [yn]? y zsh: argument list too long: rm % ls * zsh: argument list too long: ls "。抱歉,但是我看不到它与问题-1有什么关系,因为测试起来非常容易,仅创建1e6文件并运行命令。

1

locate(当然updatedb)是给你什么帮助?


1
updatedb使用find
dave1010 2011年

@ dave1010,当然可以,但它偶尔会在后台执行,因此,如果OP可以接受不必每分钟更新一次,但可能每天更新一次,则可以在一个安静的时间安​​排updateb(或频繁地计划updateb,但是优先级较低(无论如何应该这样),然后使用locate可以很快找到所需的内容。因此,关键问题是数据库(或任何其他此类系统的索引)需要如何更新。
asoundmove 2011年
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.